diff --git a/contribs/application/src/main/java/org/matsim/application/analysis/noise/NoiseAnalysis.java b/contribs/application/src/main/java/org/matsim/application/analysis/noise/NoiseAnalysis.java index eb76c273c61..c5927fcdb04 100644 --- a/contribs/application/src/main/java/org/matsim/application/analysis/noise/NoiseAnalysis.java +++ b/contribs/application/src/main/java/org/matsim/application/analysis/noise/NoiseAnalysis.java @@ -110,8 +110,8 @@ public Integer call() throws Exception { private Config prepareConfig() { Config config = ConfigUtils.loadConfig(ApplicationUtils.matchInput("config.xml", input.getRunDirectory()).toAbsolutePath().toString(), new NoiseConfigGroup()); - //it is important to match "output_vehicles" because otherwise dvrpVehicle files might be matched and the code crashes later - config.vehicles().setVehiclesFile(ApplicationUtils.matchInput("output_vehicles", input.getRunDirectory()).toAbsolutePath().toString()); + //it is important to match "output_vehicles.xml.gz" specifically, because otherwise dvrpVehicle files might be matched and the code crashes later + config.vehicles().setVehiclesFile(ApplicationUtils.matchInput("output_vehicles.xml.gz", input.getRunDirectory()).toAbsolutePath().toString()); config.network().setInputFile(ApplicationUtils.matchInput("network", input.getRunDirectory()).toAbsolutePath().toString()); config.transit().setTransitScheduleFile(null); config.transit().setVehiclesFile(null); diff --git a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/CarrierReaderFromCSV.java b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/CarrierReaderFromCSV.java index 19dc604a32c..da86aa03763 100644 --- a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/CarrierReaderFromCSV.java +++ b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/CarrierReaderFromCSV.java @@ -234,14 +234,14 @@ public void setFixedNumberOfVehiclePerTypeAndLocation(int fixedNumberOfVehiclePe /** * Reads and create the carriers with reading the information from the csv file. * - * @param scenario - * @param freightCarriersConfigGroup - * @param csvLocationCarrier - * @param indexShape - * @param defaultJspritIterations - * @param crsTransformationNetworkAndShape - * @param shapeCategory - * @throws IOException + * @param scenario Scenario + * @param freightCarriersConfigGroup FreightCarriersConfigGroup + * @param csvLocationCarrier Path to the csv file with the carrier information + * @param indexShape ShpOptions.Index for the shape file + * @param defaultJspritIterations Default number of jsprit iterations + * @param crsTransformationNetworkAndShape CoordinateTransformation for the network and shape + * @param shapeCategory Column name in the shape file for the data connection in the csv files + * @throws IOException IOException */ public static void readAndCreateCarrierFromCSV(Scenario scenario, FreightCarriersConfigGroup freightCarriersConfigGroup, Path csvLocationCarrier, ShpOptions.Index indexShape, int defaultJspritIterations, @@ -255,12 +255,12 @@ public static void readAndCreateCarrierFromCSV(Scenario scenario, FreightCarrier } /** - * @param csvLocationCarrier - * @return - * @throws IOException + * @param csvLocationCarrier Path to the csv file with the carrier information + * @return Set Set of CarrierInformationElements + * @throws IOException IOException */ static Set readCarrierInformation(Path csvLocationCarrier) throws IOException { - log.info("Start reading carrier csv file: " + csvLocationCarrier); + log.info("Start reading carrier csv file: {}", csvLocationCarrier); Set allNewCarrierInformation = new HashSet<>(); CSVParser parse = new CSVParser(Files.newBufferedReader(csvLocationCarrier), CSVFormat.Builder.create(CSVFormat.TDF).setHeader().setSkipHeaderRecord(true).build()); @@ -305,11 +305,11 @@ else if (!record.get("fleetSize").isBlank()) /** * Checks if the read carrier information is consistent. * - * @param allNewCarrierInformation - * @param freightCarriersConfigGroup - * @param scenario - * @param indexShape - * @param shapeCategory + * @param allNewCarrierInformation Set of CarrierInformationElements + * @param freightCarriersConfigGroup FreightCarriersConfigGroup + * @param scenario Scenario + * @param indexShape ShpOptions.Index for the shape file + * @param shapeCategory Column name in the shape file for the data connection in the csv files */ static void checkNewCarrier(Set allNewCarrierInformation, FreightCarriersConfigGroup freightCarriersConfigGroup, Scenario scenario, ShpOptions.Index indexShape, String shapeCategory) { @@ -346,15 +346,12 @@ static void checkNewCarrier(Set allNewCarrierInformat throw new RuntimeException( "If a vehicle type is selected in the input file, numberOfDepots or selectedVehicleDepots should be set. Please check carrier " + carrierElement.getName()); - if (carrierElement.getVehicleDepots() != null - && (carrierElement.getNumberOfDepotsPerType() > carrierElement.getVehicleDepots().size()) - && carrierElement.getAreaOfAdditionalDepots() == null) + if ((carrierElement.getVehicleDepots() != null + && (carrierElement.getNumberOfDepotsPerType() > carrierElement.getVehicleDepots().size()) + && carrierElement.getAreaOfAdditionalDepots() == null) || (carrierElement.getVehicleDepots() == null && (carrierElement.getNumberOfDepotsPerType() > 0) + && carrierElement.getAreaOfAdditionalDepots() == null)) log.warn( - "No possible area for additional depot given. Random choice in the hole network of a possible position"); - if (carrierElement.getVehicleDepots() == null && (carrierElement.getNumberOfDepotsPerType() > 0) - && carrierElement.getAreaOfAdditionalDepots() == null) - log.warn( - "No possible area for additional depot given. Random choice in the hole network of a possible position"); + "No possible area for additional depot given. Random choice in the hole network of a possible position"); if (carrierElement.getAreaOfAdditionalDepots() != null) { if (indexShape == null) throw new RuntimeException("For carrier " + carrierElement.getName() @@ -407,12 +404,12 @@ static void checkNewCarrier(Set allNewCarrierInformat /** * Read and creates the carrier and the vehicle types. * - * @param scenario - * @param allNewCarrierInformation - * @param freightCarriersConfigGroup - * @param indexShape - * @param defaultJspritIterations - * @param crsTransformationNetworkAndShape + * @param scenario Scenario + * @param allNewCarrierInformation Set of CarrierInformationElements + * @param freightCarriersConfigGroup FreightCarriersConfigGroup + * @param indexShape ShpOptions.Index for the shape file + * @param defaultJspritIterations Default number of jsprit iterations + * @param crsTransformationNetworkAndShape CoordinateTransformation for the network and shape */ static void createNewCarrierAndAddVehicleTypes(Scenario scenario, Set allNewCarrierInformation, FreightCarriersConfigGroup freightCarriersConfigGroup, @@ -498,8 +495,7 @@ static void createNewCarrierAndAddVehicleTypes(Scenario scenario, for (Carrier carrier : carriers.getCarriers().values()) { if (CarriersUtils.getJspritIterations(carrier) == Integer.MIN_VALUE) { CarriersUtils.setJspritIterations(carrier, defaultJspritIterations); - log.warn("The jspritIterations are now set to the default value of " + defaultJspritIterations - + " in this simulation!"); + log.warn("The jspritIterations are now set to the default value of {} in this simulation!", defaultJspritIterations); } } } diff --git a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/DemandReaderFromCSV.java b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/DemandReaderFromCSV.java index a301fe8dcf1..126eff63188 100644 --- a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/DemandReaderFromCSV.java +++ b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/DemandReaderFromCSV.java @@ -53,6 +53,7 @@ public final class DemandReaderFromCSV { private static final Logger log = LogManager.getLogger(DemandReaderFromCSV.class); private static final Random rand = new Random(4711); + private static double roundingError; /** * DemandInformationElement is a set of information being read from the input @@ -316,14 +317,14 @@ public String getTypeOfDemand() { * Reads the csv with the demand information and adds this demand to the related * carriers. * - * @param scenario - * @param csvLocationDemand - * @param indexShape - * @param combineSimilarJobs - * @param crsTransformationNetworkAndShape - * @param population - * @param shapeCategory - * @throws IOException + * @param scenario Scenario + * @param csvLocationDemand Path to the csv file with the demand information + * @param indexShape ShpOptions.Index for the shape file + * @param combineSimilarJobs boolean if the jobs of the same carrier with same location and time will be combined + * @param crsTransformationNetworkAndShape CoordinateTransformation for the network and shape file + * @param population Population + * @param shapeCategory Column name in the shape file for the data connection in the csv files + * @throws IOException if the csv file cannot be read */ static void readAndCreateDemand(Scenario scenario, Path csvLocationDemand, ShpOptions.Index indexShape, boolean combineSimilarJobs, @@ -339,9 +340,9 @@ static void readAndCreateDemand(Scenario scenario, Path csvLocationDemand, * Reads the demand information from the csv file and checks if the information * is consistent * - * @param csvLocationDemand - * @return - * @throws IOException + * @param csvLocationDemand Path to the csv file with the demand information + * @return Set + * @throws IOException if the csv file cannot be read */ static Set readDemandInformation(Path csvLocationDemand) throws IOException { @@ -403,10 +404,10 @@ static Set readDemandInformation(Path csvLocationDeman * Checks if the read demand information are useful to create the shipment or * service demands * - * @param scenario - * @param demandInformation - * @param indexShape - * @param shapeCategory + * @param scenario Scenario + * @param demandInformation Set + * @param indexShape ShpOptions.Index for the shape file + * @param shapeCategory Column name in the shape file for the data connection in the csv files */ static void checkNewDemand(Scenario scenario, Set demandInformation, ShpOptions.Index indexShape, String shapeCategory) { @@ -537,12 +538,12 @@ static void checkNewDemand(Scenario scenario, Set dema /** * Creates for every demand information the services/shipments for the carriers * - * @param scenario - * @param indexShape - * @param demandInformation - * @param population - * @param combineSimilarJobs - * @param crsTransformationNetworkAndShape + * @param scenario Scenario + * @param indexShape ShpOptions.Index for the shape file + * @param demandInformation Set with the demand information + * @param population Population + * @param combineSimilarJobs boolean if the jobs of the same carrier with same location and time will be combined + * @param crsTransformationNetworkAndShape CoordinateTransformation for the network and shape file */ static void createDemandForCarriers(Scenario scenario, ShpOptions.Index indexShape, Set demandInformation, Population population, boolean combineSimilarJobs, @@ -562,12 +563,12 @@ else if (newDemandInformationElement.getTypeOfDemand().equals("shipment")) /** * Creates the services. * - * @param scenario - * @param newDemandInformationElement - * @param indexShape - * @param population - * @param combineSimilarJobs - * @param crsTransformationNetworkAndShape + * @param scenario Scenario + * @param newDemandInformationElement single DemandInformationElement + * @param indexShape ShpOptions.Index + * @param population Population + * @param combineSimilarJobs boolean if the jobs of the same carrier with same location and time will be combined + * @param crsTransformationNetworkAndShape CoordinateTransformation for the network and shape file */ private static void createServices(Scenario scenario, DemandInformationElement newDemandInformationElement, ShpOptions.Index indexShape, Population population, boolean combineSimilarJobs, @@ -575,7 +576,7 @@ private static void createServices(Scenario scenario, DemandInformationElement n int countOfLinks = 1; int distributedDemand = 0; - double roundingError = 0; + roundingError = 0; Double shareOfPopulationWithThisService = newDemandInformationElement.getShareOfPopulationWithFirstJobElement(); Integer numberOfJobs; Integer demandToDistribute = newDemandInformationElement.getDemandToDistribute(); @@ -661,23 +662,11 @@ else if (samplingOption.equals("changeDemandOnLocation")) { if (numberOfServiceLocations != null) throw new RuntimeException( "Because the demand is higher than the number of links, the demand will be distributed evenly over all links. You selected a certain number of service locations, which is not possible here!"); - double sumOfPossibleLinkLength = 0; - possibleLinksForService.values().forEach(l -> Double.sum(l.getLength(), sumOfPossibleLinkLength)); + double sumOfPossibleLinkLength = possibleLinksForService.values().stream().mapToDouble(Link::getLength).sum(); for (Link link : possibleLinksForService.values()) { - int demandForThisLink; - if (countOfLinks == scenario.getNetwork().getLinks().size()) { - demandForThisLink = demandToDistribute - distributedDemand; - } else { - demandForThisLink = (int) Math - .ceil(link.getLength() / sumOfPossibleLinkLength * (double) demandToDistribute); - roundingError = roundingError + ((double) demandForThisLink - - (link.getLength() / sumOfPossibleLinkLength * (double) demandToDistribute)); - if (roundingError > 1) { - demandForThisLink = demandForThisLink - 1; - roundingError = roundingError - 1; - } - countOfLinks++; - } + int demandForThisLink = calculateDemandBasedOnLinkLength(countOfLinks, distributedDemand, demandToDistribute, possibleLinksForService.size(), + sumOfPossibleLinkLength, link); + countOfLinks++; double serviceTime = newDemandInformationElement.getFirstJobElementTimePerUnit() * demandForThisLink; Id idNewService = Id.create( @@ -715,17 +704,8 @@ else if (samplingOption.equals("changeDemandOnLocation")) { link = scenario.getNetwork().getLinks().get(Id.createLinkId(usedServiceLocations.stream() .skip(rand.nextInt(usedServiceLocations.size() - 1)).findFirst().get())); } - int demandForThisLink = (int) Math.ceil((double) demandToDistribute / (double) numberOfJobs); - if (numberOfJobs == (i + 1)) { - demandForThisLink = demandToDistribute - distributedDemand; - } else { - roundingError = roundingError - + ((double) demandForThisLink - ((double) demandToDistribute / (double) numberOfJobs)); - if (roundingError > 1) { - demandForThisLink = demandForThisLink - 1; - roundingError = roundingError - 1; - } - } + int demandForThisLink = calculateDemandForThisLink(demandToDistribute, numberOfJobs, distributedDemand, i); + double serviceTime; if (demandToDistribute == 0) serviceTime = newDemandInformationElement.getFirstJobElementTimePerUnit(); @@ -754,12 +734,12 @@ else if (samplingOption.equals("changeDemandOnLocation")) { /** * Creates the shipments of a carrier. * - * @param scenario - * @param newDemandInformationElement - * @param indexShape - * @param population - * @param combineSimilarJobs - * @param crsTransformationNetworkAndShape + * @param scenario Scenario + * @param newDemandInformationElement single DemandInformationElement + * @param indexShape ShpOptions.Index for the shape file + * @param population Population + * @param combineSimilarJobs boolean if the jobs of the same carrier with same location and time will be combined + * @param crsTransformationNetworkAndShape CoordinateTransformation for the network and shape file */ private static void createShipments(Scenario scenario, DemandInformationElement newDemandInformationElement, ShpOptions.Index indexShape, Population population, boolean combineSimilarJobs, @@ -767,7 +747,7 @@ private static void createShipments(Scenario scenario, DemandInformationElement int countOfLinks = 1; int distributedDemand = 0; - double roundingError = 0; + roundingError = 0; Double shareOfPopulationWithThisPickup = newDemandInformationElement.getShareOfPopulationWithFirstJobElement(); Double shareOfPopulationWithThisDelivery = newDemandInformationElement .getShareOfPopulationWithSecondJobElement(); @@ -817,6 +797,8 @@ else if (population == null) numberPossibleJobsDelivery = (int) Math .round(shareOfPopulationWithThisDelivery * possiblePersonsDelivery.size()); + int sampledNumberPossibleJobsPickup = (int)Math.round((sampleTo / sampleSizeInputPopulation) * numberPossibleJobsPickup); + int sampledNumberPossibleJobsDelivery = (int) Math.round((sampleTo / sampleSizeInputPopulation) * numberPossibleJobsDelivery); if (numberPossibleJobsPickup > numberPossibleJobsDelivery) { if (sampleSizeInputPopulation == sampleTo) { numberOfJobs = (int) Math.round(shareOfPopulationWithThisPickup * numberPossibleJobsPickup); @@ -825,11 +807,10 @@ else if (population == null) numberPossibleJobsDelivery = (int) Math .round(shareOfPopulationWithThisDelivery * numberPossibleJobsDelivery); } else if (samplingOption.equals("changeNumberOfLocationsWithDemand")) { - numberOfJobs = (int) Math.round((sampleTo / sampleSizeInputPopulation) * numberPossibleJobsPickup); + numberOfJobs = sampledNumberPossibleJobsPickup; numberPossibleJobsPickup = numberOfJobs; if (shareOfPopulationWithThisDelivery != null) - numberPossibleJobsDelivery = (int) Math - .round((sampleTo / sampleSizeInputPopulation) * numberPossibleJobsDelivery); + numberPossibleJobsDelivery = sampledNumberPossibleJobsDelivery; } else if (samplingOption.equals("changeDemandOnLocation")) { demandToDistribute = (int) Math.round((sampleTo / sampleSizeInputPopulation) * demandToDistribute); numberOfJobs = numberPossibleJobsPickup; @@ -843,12 +824,10 @@ else if (population == null) numberPossibleJobsPickup = (int) Math .round(shareOfPopulationWithThisPickup * numberPossibleJobsPickup); } else if (samplingOption.equals("changeNumberOfLocationsWithDemand")) { - numberOfJobs = (int) Math - .round((sampleTo / sampleSizeInputPopulation) * numberPossibleJobsDelivery); + numberOfJobs = sampledNumberPossibleJobsDelivery; numberPossibleJobsDelivery = numberOfJobs; if (shareOfPopulationWithThisDelivery != null) - numberPossibleJobsPickup = (int) Math - .round((sampleTo / sampleSizeInputPopulation) * numberPossibleJobsPickup); + numberPossibleJobsPickup = sampledNumberPossibleJobsPickup; } else if (samplingOption.equals("changeDemandOnLocation")) { demandToDistribute = (int) Math.round((sampleTo / sampleSizeInputPopulation) * demandToDistribute); numberOfJobs = numberPossibleJobsDelivery; @@ -867,7 +846,7 @@ else if (population == null) setLocationsOfPickup, possiblePersonsPickup, nearestLinkPerPersonPickup); HashMap, Link> possibleLinksDelivery = findAllPossibleLinks(scenario, indexShape, crsTransformationNetworkAndShape, numberOfDeliveryLocations, areasForDeliveryLocations, - setLocationsOfDelivery, possiblePersonsDelivery, nearestLinkPerPersonPickup); + setLocationsOfDelivery, possiblePersonsDelivery, nearestLinkPerPersonDelivery); if (possibleLinksPickup.isEmpty()) throw new RuntimeException( @@ -906,25 +885,13 @@ else if (population == null) usedDeliveryLocations, possiblePersonsDelivery, nearestLinkPerPersonDelivery, crsTransformationNetworkAndShape, i); - double serviceTimePickup = newDemandInformationElement.getFirstJobElementTimePerUnit(); - double serviceTimeDelivery = newDemandInformationElement.getSecondJobElementTimePerUnit(); - TimeWindow timeWindowPickup = newDemandInformationElement.getFirstJobElementTimeWindow(); - TimeWindow timeWindowDelivery = newDemandInformationElement.getSecondJobElementTimeWindow(); int demandForThisLink = 1; if (!usedPickupLocations.contains(linkPickup.getId().toString())) usedPickupLocations.add(linkPickup.getId().toString()); if (!usedDeliveryLocations.contains(linkDelivery.getId().toString())) usedDeliveryLocations.add(linkDelivery.getId().toString()); - Id idNewShipment = Id.create(createJobId(scenario, newDemandInformationElement, - linkPickup.getId(), linkDelivery.getId()), CarrierShipment.class); - CarrierShipment thisShipment = CarrierShipment.Builder - .newInstance(idNewShipment, linkPickup.getId(), linkDelivery.getId(), demandForThisLink) - .setPickupServiceTime(serviceTimePickup).setPickupTimeWindow(timeWindowPickup) - .setDeliveryServiceTime(serviceTimeDelivery).setDeliveryTimeWindow(timeWindowDelivery) - .build(); - CarriersUtils.getCarriers(scenario).getCarriers() - .get(Id.create(newDemandInformationElement.getCarrierName(), Carrier.class)).getShipments() - .put(thisShipment.getId(), thisShipment); + + createSingleShipment(scenario, newDemandInformationElement, linkPickup, linkDelivery, demandForThisLink); } } else // creates a demand on each link, demand depends on the length of the link @@ -935,12 +902,10 @@ else if (population == null) HashMap, Link> demandBasesLinks; double sumOfDemandBasedLinks; boolean pickupIsDemandBase = true; - Link linkPickup; - Link linkDelivery; - double sumOfPossibleLinkLengthPickup = 0; - double sumOfPossibleLinkLengthDelivery = 0; - possibleLinksPickup.values().forEach(l -> Double.sum(l.getLength(), sumOfPossibleLinkLengthPickup)); - possibleLinksDelivery.values().forEach(l -> Double.sum(l.getLength(), sumOfPossibleLinkLengthDelivery)); + Link linkPickup = null; + Link linkDelivery= null; + double sumOfPossibleLinkLengthPickup = possibleLinksPickup.values().stream().mapToDouble(Link::getLength).sum(); + double sumOfPossibleLinkLengthDelivery = possibleLinksDelivery.values().stream().mapToDouble(Link::getLength).sum(); if (numberOfPickupLocations == null && numberOfDeliveryLocations == null) if (possibleLinksPickup.size() > possibleLinksDelivery.size()) { demandBasesLinks = possibleLinksPickup; @@ -959,26 +924,11 @@ else if (numberOfPickupLocations != null) { sumOfDemandBasedLinks = sumOfPossibleLinkLengthPickup; } for (Link demandBasedLink : demandBasesLinks.values()) { - int demandForThisLink; - if (countOfLinks == demandBasesLinks.size()) { - demandForThisLink = demandToDistribute - distributedDemand; - } else { - demandForThisLink = (int) Math.ceil( - demandBasedLink.getLength() / sumOfDemandBasedLinks * (double) demandToDistribute); - roundingError = roundingError + ((double) demandForThisLink - - (demandBasedLink.getLength() / sumOfDemandBasedLinks * (double) demandToDistribute)); - if (roundingError > 1) { - demandForThisLink = demandForThisLink - 1; - roundingError = roundingError - 1; - } - } + int demandForThisLink = calculateDemandBasedOnLinkLength(countOfLinks, distributedDemand, demandToDistribute, demandBasesLinks.size(), sumOfDemandBasedLinks, + demandBasedLink); if (pickupIsDemandBase) { linkPickup = demandBasedLink; - linkDelivery = findNextUsedLink(scenario, indexShape, possibleLinksDelivery, - numberOfDeliveryLocations, areasForDeliveryLocations, setLocationsOfDelivery, - usedDeliveryLocations, possiblePersonsDelivery, nearestLinkPerPersonDelivery, - crsTransformationNetworkAndShape, countOfLinks - 1); - while (usedDeliveryLocations.contains(linkDelivery.getId().toString())) { + while (linkDelivery == null || usedDeliveryLocations.contains(linkDelivery.getId().toString())) { linkDelivery = findNextUsedLink(scenario, indexShape, possibleLinksDelivery, numberOfDeliveryLocations, areasForDeliveryLocations, setLocationsOfDelivery, usedDeliveryLocations, possiblePersonsDelivery, nearestLinkPerPersonDelivery, @@ -990,11 +940,7 @@ else if (numberOfPickupLocations != null) { } } else { linkDelivery = demandBasedLink; - linkPickup = findNextUsedLink(scenario, indexShape, possibleLinksPickup, - numberOfPickupLocations, areasForPickupLocations, setLocationsOfPickup, - usedPickupLocations, possiblePersonsPickup, nearestLinkPerPersonPickup, - crsTransformationNetworkAndShape, countOfLinks - 1); - while (usedPickupLocations.contains(linkPickup.getId().toString())) { + while (linkPickup == null || usedPickupLocations.contains(linkPickup.getId().toString())) { linkPickup = findNextUsedLink(scenario, indexShape, possibleLinksPickup, numberOfPickupLocations, areasForPickupLocations, setLocationsOfPickup, usedPickupLocations, possiblePersonsPickup, nearestLinkPerPersonPickup, @@ -1010,36 +956,24 @@ else if (numberOfPickupLocations != null) { usedPickupLocations.add(linkPickup.getId().toString()); if (!usedDeliveryLocations.contains(linkDelivery.getId().toString())) usedDeliveryLocations.add(linkDelivery.getId().toString()); - double serviceTimePickup = newDemandInformationElement.getFirstJobElementTimePerUnit() - * demandForThisLink; - double serviceTimeDelivery = newDemandInformationElement.getSecondJobElementTimePerUnit() - * demandForThisLink; - TimeWindow timeWindowPickup = newDemandInformationElement.getFirstJobElementTimeWindow(); - TimeWindow timeWindowDelivery = newDemandInformationElement.getSecondJobElementTimeWindow(); - Id idNewShipment = Id.create(createJobId(scenario, newDemandInformationElement, - linkPickup.getId(), linkDelivery.getId()), CarrierShipment.class); + if (demandForThisLink > 0) { - CarrierShipment thisShipment = CarrierShipment.Builder - .newInstance(idNewShipment, linkPickup.getId(), linkDelivery.getId(), demandForThisLink) - .setPickupServiceTime(serviceTimePickup).setPickupTimeWindow(timeWindowPickup) - .setDeliveryServiceTime(serviceTimeDelivery).setDeliveryTimeWindow(timeWindowDelivery) - .build(); - CarriersUtils.getCarriers(scenario).getCarriers() - .get(Id.create(newDemandInformationElement.getCarrierName(), Carrier.class)) - .getShipments().put(thisShipment.getId(), thisShipment); + createSingleShipment(scenario, newDemandInformationElement, linkPickup, linkDelivery, + demandForThisLink); } distributedDemand = distributedDemand + demandForThisLink; } } } else - // if a certain number of shipments is selected { for (int i = 0; i < numberOfJobs; i++) { - if (demandToDistribute != 0 && demandToDistribute < numberOfJobs) - throw new RuntimeException( - "The resulting number of jobs is not feasible, because the demand is smaller then the number of jobs. Please check!"); + if (demandToDistribute != 0 && demandToDistribute < numberOfJobs) { + numberOfJobs = demandToDistribute; + log.warn( + "The resulting number of jobs is not feasible, because the demand is smaller then the number of jobs. Number of jobs is reduced to demand!"); + } Link linkPickup = findNextUsedLink(scenario, indexShape, possibleLinksPickup, numberOfPickupLocations, areasForPickupLocations, setLocationsOfPickup, usedPickupLocations, possiblePersonsPickup, nearestLinkPerPersonPickup, crsTransformationNetworkAndShape, i); @@ -1047,43 +981,15 @@ else if (numberOfPickupLocations != null) { numberOfDeliveryLocations, areasForDeliveryLocations, setLocationsOfDelivery, usedDeliveryLocations, possiblePersonsDelivery, nearestLinkPerPersonDelivery, crsTransformationNetworkAndShape, i); - int demandForThisLink = (int) Math.ceil((double) demandToDistribute / (double) numberOfJobs); - if (numberOfJobs == (i + 1)) - demandForThisLink = demandToDistribute - distributedDemand; - else { - roundingError = roundingError - + ((double) demandForThisLink - ((double) demandToDistribute / (double) numberOfJobs)); - if (roundingError > 1) { - demandForThisLink = demandForThisLink - 1; - roundingError = roundingError - 1; - } - } + int demandForThisLink = calculateDemandForThisLink(demandToDistribute, numberOfJobs, distributedDemand, i); + if (!usedPickupLocations.contains(linkPickup.getId().toString())) usedPickupLocations.add(linkPickup.getId().toString()); if (!usedDeliveryLocations.contains(linkDelivery.getId().toString())) usedDeliveryLocations.add(linkDelivery.getId().toString()); - double serviceTimePickup; - double serviceTimeDelivery; - if (demandForThisLink == 0) { - serviceTimePickup = newDemandInformationElement.getFirstJobElementTimePerUnit(); - serviceTimeDelivery = newDemandInformationElement.getSecondJobElementTimePerUnit(); - } else { - serviceTimePickup = newDemandInformationElement.getFirstJobElementTimePerUnit() * demandForThisLink; - serviceTimeDelivery = newDemandInformationElement.getSecondJobElementTimePerUnit() - * demandForThisLink; - } - TimeWindow timeWindowPickup = newDemandInformationElement.getFirstJobElementTimeWindow(); - TimeWindow timeWindowDelivery = newDemandInformationElement.getSecondJobElementTimeWindow(); - Id idNewShipment = Id.create( - createJobId(scenario, newDemandInformationElement, linkPickup.getId(), linkDelivery.getId()), - CarrierShipment.class); - CarrierShipment thisShipment = CarrierShipment.Builder - .newInstance(idNewShipment, linkPickup.getId(), linkDelivery.getId(), demandForThisLink) - .setPickupServiceTime(serviceTimePickup).setPickupTimeWindow(timeWindowPickup) - .setDeliveryServiceTime(serviceTimeDelivery).setDeliveryTimeWindow(timeWindowDelivery).build(); - CarriersUtils.getCarriers(scenario).getCarriers() - .get(Id.create(newDemandInformationElement.getCarrierName(), Carrier.class)).getShipments() - .put(thisShipment.getId(), thisShipment); + + createSingleShipment(scenario, newDemandInformationElement, linkPickup, linkDelivery, + demandForThisLink); distributedDemand = distributedDemand + demandForThisLink; } } @@ -1091,15 +997,50 @@ else if (numberOfPickupLocations != null) { reduceNumberOfJobsIfSameCharacteristics(scenario, newDemandInformationElement); } + /** Creates a single shipment. + * @param scenario Scenario + * @param newDemandInformationElement single DemandInformationElement + * @param linkPickup Link for the pickup + * @param linkDelivery Link for the delivery + * @param demandForThisLink Demand for this link + */ + private static void createSingleShipment(Scenario scenario, DemandInformationElement newDemandInformationElement, + Link linkPickup, Link linkDelivery, int demandForThisLink) { + + Id idNewShipment = Id.create(createJobId(scenario, newDemandInformationElement, + linkPickup.getId(), linkDelivery.getId()), CarrierShipment.class); + + TimeWindow timeWindowPickup = newDemandInformationElement.getFirstJobElementTimeWindow(); + TimeWindow timeWindowDelivery = newDemandInformationElement.getSecondJobElementTimeWindow(); + + double serviceTimePickup; + double serviceTimeDelivery; + if (demandForThisLink == 0) { + serviceTimePickup = newDemandInformationElement.getFirstJobElementTimePerUnit(); + serviceTimeDelivery = newDemandInformationElement.getSecondJobElementTimePerUnit(); + } else { + serviceTimePickup = newDemandInformationElement.getFirstJobElementTimePerUnit() * demandForThisLink; + serviceTimeDelivery = newDemandInformationElement.getSecondJobElementTimePerUnit() * demandForThisLink; + } + CarrierShipment thisShipment = CarrierShipment.Builder + .newInstance(idNewShipment, linkPickup.getId(), linkDelivery.getId(), demandForThisLink) + .setPickupServiceTime(serviceTimePickup).setPickupTimeWindow(timeWindowPickup) + .setDeliveryServiceTime(serviceTimeDelivery).setDeliveryTimeWindow(timeWindowDelivery) + .build(); + CarriersUtils.getCarriers(scenario).getCarriers() + .get(Id.create(newDemandInformationElement.getCarrierName(), Carrier.class)).getShipments() + .put(thisShipment.getId(), thisShipment); + } + /** * Creates a job Id for a new job. * If a certain Id is already used, a number will be added at the end until no existing job was the same Id. * - * @param scenario - * @param newDemandInformationElement - * @param linkPickup - * @param linkDelivery - * @return + * @param scenario Scenario + * @param newDemandInformationElement single DemandInformationElement + * @param linkPickup Link for the pickup + * @param linkDelivery Link for the delivery + * @return New Job Id */ private static String createJobId(Scenario scenario, DemandInformationElement newDemandInformationElement, Id linkPickup, Id linkDelivery) { @@ -1130,12 +1071,61 @@ private static String createJobId(Scenario scenario, DemandInformationElement ne return newJobId; } + /** Calculates the demand for this link including checking the rounding error. + * @param demandToDistribute Demand to distribute + * @param numberOfJobs Number of jobs + * @param distributedDemand Already Distributed demand + * @param i Counter + * @return Demand for this link + */ + private static int calculateDemandForThisLink(int demandToDistribute, int numberOfJobs, int distributedDemand, int i) { + + int demandForThisLink = (int) Math.ceil((double) demandToDistribute / (double) numberOfJobs); + if (numberOfJobs == (i + 1)) { + demandForThisLink = demandToDistribute - distributedDemand; + } else { + roundingError = roundingError + + ((double) demandForThisLink - ((double) demandToDistribute / (double) numberOfJobs)); + if (roundingError > 1) { + demandForThisLink = demandForThisLink - 1; + roundingError = roundingError - 1; + } + } + return demandForThisLink; + } + + /** + * @param countOfLinks counter + * @param distributedDemand Already distributed demand + * @param demandToDistribute Demand to distribute + * @param maxLinks Maximum of possible links for demand + * @param sumOfPossibleLinkLength Sum of all lengths of the links + * @param link this link + * @return Demand for this link + */ + private static int calculateDemandBasedOnLinkLength(int countOfLinks, int distributedDemand, Integer demandToDistribute, + int maxLinks, double sumOfPossibleLinkLength, Link link) { + int demandForThisLink; + if (countOfLinks == maxLinks) { + demandForThisLink = demandToDistribute - distributedDemand; + } else { + demandForThisLink = (int) Math + .ceil(link.getLength() / sumOfPossibleLinkLength * (double) demandToDistribute); + roundingError = roundingError + ((double) demandForThisLink + - (link.getLength() / sumOfPossibleLinkLength * (double) demandToDistribute)); + if (roundingError > 1) { + demandForThisLink = demandForThisLink - 1; + roundingError = roundingError - 1; + } + } + return demandForThisLink; + } /** * If jobs of a carrier have the same characteristics (time window, location), * they will be combined to one job. * - * @param scenario - * @param newDemandInformationElement + * @param scenario Scenario + * @param newDemandInformationElement single DemandInformationElement */ private static void reduceNumberOfJobsIfSameCharacteristics(Scenario scenario, DemandInformationElement newDemandInformationElement) { @@ -1144,14 +1134,14 @@ private static void reduceNumberOfJobsIfSameCharacteristics(Scenario scenario, "The number of Jobs will be reduced if jobs have the same characteristics (e.g. time, location, carrier)"); int connectedJobs = 0; if (newDemandInformationElement.getTypeOfDemand().equals("shipment")) { - HashMap, CarrierShipment> shipmentsToRemove = new HashMap, CarrierShipment>(); - ArrayList shipmentsToAdd = new ArrayList(); + HashMap, CarrierShipment> shipmentsToRemove = new HashMap<>(); + ArrayList shipmentsToAdd = new ArrayList<>(); Carrier thisCarrier = CarriersUtils.getCarriers(scenario).getCarriers() .get(Id.create(newDemandInformationElement.getCarrierName(), Carrier.class)); for (Id baseShipmentId : thisCarrier.getShipments().keySet()) { if (!shipmentsToRemove.containsKey(baseShipmentId)) { CarrierShipment baseShipment = thisCarrier.getShipments().get(baseShipmentId); - HashMap, CarrierShipment> shipmentsToConnect = new HashMap, CarrierShipment>(); + HashMap, CarrierShipment> shipmentsToConnect = new HashMap<>(); shipmentsToConnect.put(baseShipmentId, baseShipment); for (Id thisShipmentId : thisCarrier.getShipments().keySet()) { if (!shipmentsToRemove.containsKey(thisShipmentId)) { @@ -1192,17 +1182,17 @@ private static void reduceNumberOfJobsIfSameCharacteristics(Scenario scenario, for (CarrierShipment carrierShipment : shipmentsToAdd) { thisCarrier.getShipments().put(carrierShipment.getId(), carrierShipment); } - log.warn("Number of reduced shipments: " + connectedJobs); + log.warn("Number of reduced shipments: {}", connectedJobs); } if (newDemandInformationElement.getTypeOfDemand().equals("service")) { - HashMap, CarrierService> servicesToRemove = new HashMap, CarrierService>(); - ArrayList servicesToAdd = new ArrayList(); + HashMap, CarrierService> servicesToRemove = new HashMap<>(); + ArrayList servicesToAdd = new ArrayList<>(); Carrier thisCarrier = CarriersUtils.getCarriers(scenario).getCarriers() .get(Id.create(newDemandInformationElement.getCarrierName(), Carrier.class)); for (Id baseServiceId : thisCarrier.getServices().keySet()) { if (!servicesToRemove.containsKey(baseServiceId)) { CarrierService baseService = thisCarrier.getServices().get(baseServiceId); - HashMap, CarrierService> servicesToConnect = new HashMap, CarrierService>(); + HashMap, CarrierService> servicesToConnect = new HashMap<>(); servicesToConnect.put(baseServiceId, baseService); for (Id thisServiceId : thisCarrier.getServices().keySet()) { if (!servicesToRemove.containsKey(thisServiceId)) { @@ -1236,29 +1226,29 @@ private static void reduceNumberOfJobsIfSameCharacteristics(Scenario scenario, for (CarrierService carrierService : servicesToAdd) { thisCarrier.getServices().put(carrierService.getId(), carrierService); } - log.warn("Number of reduced shipments: " + connectedJobs); + log.warn("Number of reduced shipments: {}", connectedJobs); } } /** * Finds and returns all possible links for this job. * - * @param scenario - * @param indexShape - * @param crsTransformationNetworkAndShape - * @param numberOfLocations - * @param areasForLocations - * @param setLocations - * @param possiblePersons - * @param nearestLinkPerPerson - * @return + * @param scenario Scenario + * @param indexShape ShpOptions.Index for the shape file + * @param crsTransformationNetworkAndShape CoordinateTransformation for the network and shape file + * @param numberOfLocations Number of locations for this demand + * @param areasForLocations Areas for the locations + * @param setLocations Selected locations + * @param possiblePersons Persons that are possible for this demand + * @param nearestLinkPerPerson Nearest link for each person + * @return HashMap with all possible links */ private static HashMap, Link> findAllPossibleLinks(Scenario scenario, ShpOptions.Index indexShape, CoordinateTransformation crsTransformationNetworkAndShape, Integer numberOfLocations, String[] areasForLocations, String[] setLocations, HashMap, Person> possiblePersons, HashMap, HashMap> nearestLinkPerPerson) { - HashMap, Link> possibleLinks = new HashMap, Link>(); + HashMap, Link> possibleLinks = new HashMap<>(); if (numberOfLocations == null) { for (Link link : scenario.getNetwork().getLinks().values()) if (!link.getId().toString().contains("pt") && (!link.getAttributes().getAsMap().containsKey( @@ -1275,27 +1265,28 @@ private static HashMap, Link> findAllPossibleLinks(Scenario scenario, crsTransformationNetworkAndShape); if (!possibleLinks.containsKey(newPossibleLink.getId())) possibleLinks.put(newPossibleLink.getId(), newPossibleLink); + if (nearestLinkPerPerson.size() == possiblePersons.size()) + break; } } - return possibleLinks; } /** * Finds the next link which can be used as a location. * - * @param scenario - * @param indexShape - * @param possibleLinks - * @param selectedNumberOfLocations - * @param areasForLocations - * @param selectedLocations - * @param usedLocations - * @param possiblePersons - * @param nearestLinkPerPerson - * @param crsTransformationNetworkAndShape - * @param i - * @return + * @param scenario Scenario + * @param indexShape ShpOptions.Index for the shape file + * @param possibleLinks All possible links + * @param selectedNumberOfLocations Number of locations for this demand + * @param areasForLocations Areas for the locations + * @param selectedLocations Selected locations + * @param usedLocations Already used locations for this demand + * @param possiblePersons Persons that are possible for this demand + * @param nearestLinkPerPerson Nearest link for each person + * @param crsTransformationNetworkAndShape CoordinateTransformation for the network and shape file + * @param i Counter for the number of locations + * @return Next link for the demand */ private static Link findNextUsedLink(Scenario scenario, ShpOptions.Index indexShape, HashMap, Link> possibleLinks, Integer selectedNumberOfLocations, String[] areasForLocations, @@ -1323,17 +1314,17 @@ private static Link findNextUsedLink(Scenario scenario, ShpOptions.Index indexSh /** * Finds all persons that are possible for the demand. * - * @param population - * @param areasForServiceLocations - * @param indexShape - * @param crsTransformationNetworkAndShape - * @return + * @param population Population + * @param areasForJobElementLocations Areas for the locations + * @param indexShape ShpOptions.Index for the shape file + * @param crsTransformationNetworkAndShape CoordinateTransformation for the network and shape file + * @return HashMap with all possible persons */ private static HashMap, Person> findPossiblePersons(Population population, - String[] areasForServiceLocations, ShpOptions.Index indexShape, + String[] areasForJobElementLocations, ShpOptions.Index indexShape, CoordinateTransformation crsTransformationNetworkAndShape) { - HashMap, Person> possiblePersons = new HashMap, Person>(); + HashMap, Person> possiblePersons = new HashMap<>(); for (Person person : population.getPersons().values()) { Coord coord = getHomeCoord(person); @@ -1341,7 +1332,7 @@ private static HashMap, Person> findPossiblePersons(Population popula coord = crsTransformationNetworkAndShape.transform(coord); if (FreightDemandGenerationUtils.checkPositionInShape(null, coord, indexShape, - areasForServiceLocations, crsTransformationNetworkAndShape)) + areasForJobElementLocations, crsTransformationNetworkAndShape)) possiblePersons.put(person.getId(), person); } return possiblePersons; @@ -1350,9 +1341,9 @@ private static HashMap, Person> findPossiblePersons(Population popula /** * Finds the nearest link for one person. * - * @param scenario - * @param nearestLinkPerPerson - * @param person + * @param scenario Scenario + * @param nearestLinkPerPerson HashMap with the nearest link for each person + * @param person Person for which the nearest link should be found */ static void findLinksForPerson(Scenario scenario, HashMap, HashMap> nearestLinkPerPerson, Person person) { @@ -1376,8 +1367,8 @@ static void findLinksForPerson(Scenario scenario, * The default is to get the home coordinate from one home activity of the selected plan. * If the selected plan does not contain a home activity, the home coordinate is read from the attributes of the person. * - * @param person The person for which the home coordinate should be returned. - * @return + * @param person The person for which the home coordinate should be returned. + * @return The home coordinate of the person. */ private static Coord getHomeCoord(Person person) { Coord homeCoord = null; @@ -1398,16 +1389,16 @@ private static Coord getHomeCoord(Person person) { /** * Searches a possible link for the demand. * - * @param possibleLinks - * @param possiblePersons - * @param nearestLinkPerPerson - * @param indexShape - * @param areasForTheDemand - * @param selectedNumberOfLocations - * @param scenario - * @param selectedLocations - * @param crsTransformationNetworkAndShape - * @return + * @param possibleLinks HashMap with all possible links + * @param possiblePersons HashMap with all possible persons + * @param nearestLinkPerPerson Nearest link for each person + * @param indexShape ShpOptions.Index for the shape file + * @param areasForTheDemand Areas for the demand + * @param selectedNumberOfLocations Number of locations for this demand + * @param scenario Scenario + * @param selectedLocations Selected locations + * @param crsTransformationNetworkAndShape CoordinateTransformation for the network and shape file + * @return The selected link for the demand */ private static Link findPossibleLinkForDemand(HashMap, Link> possibleLinks, HashMap, Person> possiblePersons, @@ -1415,7 +1406,7 @@ private static Link findPossibleLinkForDemand(HashMap, Link> possibleLi ShpOptions.Index indexShape, String[] areasForTheDemand, Integer selectedNumberOfLocations, Scenario scenario, String[] selectedLocations, CoordinateTransformation crsTransformationNetworkAndShape) { Link selectedlink = null; - Link newLink = null; + Link newLink; if (selectedNumberOfLocations == null) selectedNumberOfLocations = 0; while (selectedlink == null) { diff --git a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGeneration.java b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGeneration.java index d43ee64522e..76dda11fc9b 100644 --- a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGeneration.java +++ b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGeneration.java @@ -179,7 +179,7 @@ public Integer call() throws IOException, InvalidAttributeValueException, Execut setNetworkAndNetworkChangeEvents(config, networkPathOfOtherNetwork, networkChangeEventsFilePath); // load or create carrierVehicle - log.info("Start creating carriers. Selected option: " + selectedCarrierInputOption); + log.info("Start creating carriers. Selected option: {}", selectedCarrierInputOption); prepareVehicles(config, vehicleTypesFileLocation); // load or create carrier @@ -188,16 +188,16 @@ public Integer call() throws IOException, InvalidAttributeValueException, Execut ShpOptions.Index indexShape = null; shp = new ShpOptions(shapeFilePath, shapeCRS, null); if (shp.isDefined()) { - log.warn("Use of shpFile. Locations for the carriers and the demand only in shp: " + shp.getShapeFile()); + log.warn("Use of shpFile. Locations for the carriers and the demand only in shp: {}", shp.getShapeFile()); indexShape = shp.createIndex(shapeCategory); crsTransformationFromNetworkToShape = shp.createTransformation(networkCRS); } - log.info("Start creating carriers. Selected option: " + selectedCarrierInputOption); + log.info("Start creating carriers. Selected option: {}", selectedCarrierInputOption); createCarrier(scenario, selectedCarrierInputOption, csvCarrierPath, indexShape, defaultJspritIterations, crsTransformationFromNetworkToShape); // create the demand - log.info("Start creating the demand. Selected option: " + selectedCarrierInputOption); + log.info("Start creating the demand. Selected option: {}", selectedCarrierInputOption); createDemand(selectedDemandGenerationOption, scenario, csvDemandPath, indexShape, populationFilePath, selectedPopulationSamplingOption, selectedPopulationOption, Boolean.getBoolean(combineSimilarJobs), crsTransformationFromNetworkToShape); @@ -216,9 +216,9 @@ public Integer call() throws IOException, InvalidAttributeValueException, Execut /** * Deletes the existing output file and sets the number of the last iteration * - * @param lastMATSimIteration - * @param coordinateSystem - * @return + * @param lastMATSimIteration the last iteration of MATSim + * @param coordinateSystem global coordinate system + * @return Config */ private Config prepareConfig(int lastMATSimIteration, String coordinateSystem) { Config config = ConfigUtils.createConfig(); @@ -243,10 +243,10 @@ private Config prepareConfig(int lastMATSimIteration, String coordinateSystem) { /** * Sets the network and the networkChangeEvents if they are available. * - * @param config - * @param networkPathOfOtherNetwork - * @param networkChangeEventsFileLocation - * @throws RuntimeException + * @param config Config + * @param networkPathOfOtherNetwork path to the network + * @param networkChangeEventsFileLocation path to the networkChangeEvents + * @throws RuntimeException if the networkPathOfOtherNetwork is empty */ private static void setNetworkAndNetworkChangeEvents(Config config, String networkPathOfOtherNetwork, String networkChangeEventsFileLocation) throws RuntimeException { @@ -255,11 +255,11 @@ private static void setNetworkAndNetworkChangeEvents(Config config, String netwo throw new RuntimeException("no correct network path network"); else { config.network().setInputFile(networkPathOfOtherNetwork); - log.info("The following input network is selected: imported network from " + networkPathOfOtherNetwork); + log.info("The following input network is selected: imported network from {}", networkPathOfOtherNetwork); if (networkChangeEventsFileLocation.isEmpty()) log.info("No networkChangeEvents selected"); else { - log.info("Setting networkChangeEventsInput file: " + networkChangeEventsFileLocation); + log.info("Setting networkChangeEventsInput file: {}", networkChangeEventsFileLocation); config.network().setTimeVariantNetwork(true); config.network().setChangeEventsInputFile(networkChangeEventsFileLocation); } @@ -269,8 +269,8 @@ private static void setNetworkAndNetworkChangeEvents(Config config, String netwo /** * Reads the carrier vehicle file. * - * @param config - * @param vehicleTypesFileLocation + * @param config Config + * @param vehicleTypesFileLocation path to the vehicleTypes */ private static void prepareVehicles(Config config, String vehicleTypesFileLocation) { @@ -279,20 +279,20 @@ private static void prepareVehicles(Config config, String vehicleTypesFileLocati throw new RuntimeException("No path to the vehicleTypes selected"); else { freightCarriersConfigGroup.setCarriersVehicleTypesFile(vehicleTypesFileLocation); - log.info("Get vehicleTypes from: " + vehicleTypesFileLocation); + log.info("Get vehicleTypes from: {}", vehicleTypesFileLocation); } } /** * Differs between the different options of creating the carrier. * - * @param scenario - * @param selectedCarrierInputOption - * @param csvLocationCarrier - * @param indexShape - * @param defaultJspritIterations - * @param crsTransformationNetworkAndShape - * @throws IOException + * @param scenario Scenario + * @param selectedCarrierInputOption selected carrier input option + * @param csvLocationCarrier path to the carrier csv + * @param indexShape shape index of the shape file + * @param defaultJspritIterations default number of jsprit iterations + * @param crsTransformationNetworkAndShape transformation of the network and shape + * @throws IOException if the carrier file is not found */ private void createCarrier(Scenario scenario, CarrierInputOptions selectedCarrierInputOption, Path csvLocationCarrier, ShpOptions.Index indexShape, @@ -333,16 +333,16 @@ private void createCarrier(Scenario scenario, CarrierInputOptions selectedCarrie /** * Differs between the different options of creating the demand. * - * @param selectedDemandGenerationOption - * @param scenario - * @param csvLocationDemand - * @param indexShape - * @param populationFilePath - * @param selectedSamplingOption - * @param selectedPopulationOption - * @param combineSimilarJobs - * @param crsTransformationNetworkAndShape - * @throws IOException + * @param selectedDemandGenerationOption selected demand generation option + * @param scenario Scenario + * @param csvLocationDemand path to the demand csv + * @param indexShape shape index of the shape file + * @param populationFilePath path to the population file + * @param selectedSamplingOption selected population sampling option + * @param selectedPopulationOption selected population option + * @param combineSimilarJobs boolean if the jobs of the same carrier with same location and time will be combined + * @param crsTransformationNetworkAndShape transformation of the network and shape + * @throws IOException if the demand file is not found */ private void createDemand(DemandGenerationOptions selectedDemandGenerationOption, Scenario scenario, Path csvLocationDemand, ShpOptions.Index indexShape, String populationFilePath, @@ -407,10 +407,10 @@ private void createDemand(DemandGenerationOptions selectedDemandGenerationOption boolean oneCarrierHasJobs = false; for (Carrier carrier : CarriersUtils.getCarriers(scenario).getCarriers().values()) if (carrier.getServices().isEmpty() && carrier.getShipments().isEmpty()) - log.warn(carrier.getId().toString() + " has no jobs which can be used"); + log.warn("{} has no jobs which can be used", carrier.getId().toString()); else { oneCarrierHasJobs = true; - log.info("Used the demand of the carrier " + carrier.getId().toString() + " from the carrierFile!"); + log.info("Used the demand of the carrier {} from the carrierFile!", carrier.getId().toString()); } if (!oneCarrierHasJobs) throw new RuntimeException("Minimum one carrier has no jobs"); @@ -422,8 +422,8 @@ private void createDemand(DemandGenerationOptions selectedDemandGenerationOption /** * Prepares the controller. * - * @param scenario - * @return + * @param scenario Scenario + * @return Controler */ private static Controler prepareControler(Scenario scenario) { Controler controler = new Controler(scenario); @@ -440,76 +440,46 @@ public void install() { /** * Differs between the different options for solving the VRP problem. * - * @param selectedSolution - * @param config - * @param controler - * @throws ExecutionException - * @throws InterruptedException + * @param selectedSolution selected solution option + * @param config Config + * @param controler Controler + * @throws ExecutionException if the execution of the jsprit fails + * @throws InterruptedException if the execution of the jsprit is interrupted */ private static void solveSelectedSolution(OptionsOfVRPSolutions selectedSolution, Config config, Controler controler) throws ExecutionException, InterruptedException { + new CarrierPlanWriter((Carriers) controler.getScenario().getScenarioElement("carriers")) + .write(config.controller().getOutputDirectory() + "/output_carriersNoPlans.xml"); + if (Objects.requireNonNull(selectedSolution) == OptionsOfVRPSolutions.createNoSolutionAndOnlyWriteCarrierFile) { + log.warn( + "##Finished without solution of the VRP. If you also want to run jsprit and/or MATSim, please change case of optionsOfVRPSolutions"); + System.exit(0); + } + boolean runMatSim = false; switch (selectedSolution) { - case runJspritAndMATSim -> { - // solves the VRP with jsprit and runs MATSim afterward - new CarrierPlanWriter((Carriers) controler.getScenario().getScenarioElement("carriers")) - .write(config.controller().getOutputDirectory() + "/output_carriersNoPlans.xml"); - runJsprit(controler, false); - controler.run(); - new CarrierPlanWriter((Carriers) controler.getScenario().getScenarioElement("carriers")) - .write(config.controller().getOutputDirectory() + "/output_carriersWithPlans.xml"); - } - case runJspritAndMATSimWithDistanceConstraint -> { - // solves the VRP with jsprit by using the distance constraint and runs MATSim afterward - new CarrierPlanWriter((Carriers) controler.getScenario().getScenarioElement("carriers")) - .write(config.controller().getOutputDirectory() + "/output_carriersNoPlans.xml"); - runJsprit(controler, true); - controler.run(); - new CarrierPlanWriter((Carriers) controler.getScenario().getScenarioElement("carriers")) - .write(config.controller().getOutputDirectory() + "/output_carriersWithPlans.xml"); - } - case runJsprit -> { - // solves only the VRP with jsprit - new CarrierPlanWriter((Carriers) controler.getScenario().getScenarioElement("carriers")) - .write(config.controller().getOutputDirectory() + "/output_carriersNoPlans.xml"); - runJsprit(controler, false); - new CarrierPlanWriter((Carriers) controler.getScenario().getScenarioElement("carriers")) - .write(config.controller().getOutputDirectory() + "/output_carriersWithPlans.xml"); - log.warn( - "##Finished with the jsprit solution. If you also want to run MATSim, please change case of optionsOfVRPSolutions"); - System.exit(0); - } - case runJspritWithDistanceConstraint -> { - // solves only the VRP with jsprit by using the distance constraint - new CarrierPlanWriter((Carriers) controler.getScenario().getScenarioElement("carriers")) - .write(config.controller().getOutputDirectory() + "/output_carriersNoPlans.xml"); - runJsprit(controler, true); - new CarrierPlanWriter((Carriers) controler.getScenario().getScenarioElement("carriers")) - .write(config.controller().getOutputDirectory() + "/output_carriersWithPlans.xml"); - log.warn( - "##Finished with the jsprit solution. If you also want to run MATSim, please change case of optionsOfVRPSolutions"); - System.exit(0); - } - case createNoSolutionAndOnlyWriteCarrierFile -> { - // creates no solution of the VRP and only writes the carrier file with the - // generated carriers and demands - new CarrierPlanWriter((Carriers) controler.getScenario().getScenarioElement("carriers")) - .write(config.controller().getOutputDirectory() + "/output_carriersNoPlans.xml"); - log.warn( - "##Finished without solution of the VRP. If you also want to run jsprit and/or MATSim, please change case of optionsOfVRPSolutions"); - System.exit(0); - } - default -> { - } + case runJspritAndMATSim, runJspritAndMATSimWithDistanceConstraint -> runMatSim = true; + } + boolean useDistanceConstraint = false; + switch (selectedSolution) { + case runJspritWithDistanceConstraint, runJspritAndMATSimWithDistanceConstraint -> useDistanceConstraint = true; } + runJsprit(controler, useDistanceConstraint); + if (runMatSim) + controler.run(); + else + log.warn( + "##Finished with the jsprit solution. If you also want to run MATSim, please change case of optionsOfVRPSolutions"); + new CarrierPlanWriter((Carriers) controler.getScenario().getScenarioElement("carriers")) + .write(config.controller().getOutputDirectory() + "/output_carriersWithPlans.xml"); } /** * Runs jsprit. * - * @param controler - * @param usingRangeRestriction - * @throws ExecutionException - * @throws InterruptedException + * @param controler Controller + * @param usingRangeRestriction boolean if the range restriction is used + * @throws ExecutionException if the execution of the jsprit fails + * @throws InterruptedException if the execution of the jsprit is interrupted */ private static void runJsprit(Controler controler, boolean usingRangeRestriction) throws ExecutionException, InterruptedException { diff --git a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGenerationUtils.java b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGenerationUtils.java index 234d657c0b6..c60a8a39390 100644 --- a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGenerationUtils.java +++ b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGenerationUtils.java @@ -58,10 +58,10 @@ public class FreightDemandGenerationUtils { /** * Adds the home coordinates to attributes and removes plans * - * @param population - * @param sampleSizeInputPopulation - * @param sampleTo - * @param samplingOption + * @param population The population to be prepared + * @param sampleSizeInputPopulation The sample size of the input population + * @param sampleTo The sample to which the population should be prepared + * @param samplingOption The sampling option to be used for the population */ static void preparePopulation(Population population, double sampleSizeInputPopulation, double sampleTo, String samplingOption) { @@ -107,7 +107,7 @@ static void preparePopulation(Population population, double sampleSizeInputPopul person.getAttributes().putAttribute("homeX", homeCoord.getX()); person.getAttributes().putAttribute("homeY", homeCoord.getY()); } else { - log.warn("No home found for person " + person.getId()); + log.warn("No home found for person {}", person.getId()); } person.removePlan(person.getSelectedPlan()); } @@ -118,7 +118,7 @@ static void preparePopulation(Population population, double sampleSizeInputPopul /** * Creates a tsv file with the locations of all created demand elements. * - * @param controler + * @param controler The controller to get the network from */ static void createDemandLocationsFile(Controler controler) { @@ -160,8 +160,8 @@ static void createDemandLocationsFile(Controler controler) { /** * Reduces the population to all persons having their home in the shape * - * @param population - * @param index + * @param population The population to be reduced + * @param index The index of the shape */ static void reducePopulationToShapeArea(Population population, ShpOptions.Index index) { @@ -187,12 +187,12 @@ static void reducePopulationToShapeArea(Population population, ShpOptions.Index /** * Checks if a link is one of the possible areas. * - * @param link - * @param givenCoord - * @param indexShape - * @param possibleAreas - * @param crsTransformationNetworkAndShape - * @return + * @param link The link to be checked + * @param givenCoord The coord to be checked + * @param indexShape The index of the shape + * @param possibleAreas The possible areas + * @param crsTransformationNetworkAndShape The transformation to be used for the network and the shape + * @return True if the link is in one of the possible areas */ static boolean checkPositionInShape(Link link, Coord givenCoord, ShpOptions.Index indexShape, String[] possibleAreas, CoordinateTransformation crsTransformationNetworkAndShape) { @@ -221,8 +221,8 @@ static boolean checkPositionInShape(Link link, Coord givenCoord, ShpOptions.Inde /** * Creates the middle coord of a link. * - * @param link - * @return Middle coord of the Link + * @param link The link to be used + * @return Middle coord of the Link */ static Coord getCoordOfMiddlePointOfLink(Link link) { diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/dashboards/CreateDrtDashboard.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/dashboards/CreateDrtDashboard.java new file mode 100644 index 00000000000..382ee1214d5 --- /dev/null +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/dashboards/CreateDrtDashboard.java @@ -0,0 +1,87 @@ +/* *********************************************************************** * + * project: org.matsim.* + * Controler.java + * * + * *********************************************************************** * + * * + * copyright : (C) 2007 by the members listed in the COPYING, * + * LICENSE and WARRANTY file. * + * email : info at matsim dot org * + * * + * *********************************************************************** * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * See also COPYING, LICENSE and WARRANTY file * + * * + * *********************************************************************** */ + +package org.matsim.contrib.drt.extension.dashboards; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.application.ApplicationUtils; +import org.matsim.application.MATSimAppCommand; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.simwrapper.SimWrapper; +import org.matsim.simwrapper.SimWrapperConfigGroup; +import picocli.CommandLine; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.List; + +@CommandLine.Command( + name = "drt", + description = "Run DRT analysis and create SimWrapper dashboard for existing run output." +) +final class CreateDrtDashboard implements MATSimAppCommand { + + private static final Logger log = LogManager.getLogger(CreateDrtDashboard.class); + + @CommandLine.Parameters(arity = "1..*", description = "Path to run output directories for which DRT dashboards are to be generated.") + private List inputPaths; + + private CreateDrtDashboard(){ + } + + @Override + public Integer call() throws Exception { + + for (Path runDirectory : inputPaths) { + log.info("Running on {}", runDirectory); + + Path configPath = ApplicationUtils.matchInput("config.xml", runDirectory); + Config config = ConfigUtils.loadConfig(configPath.toString()); + SimWrapper sw = SimWrapper.create(config); + + SimWrapperConfigGroup simwrapperCfg = ConfigUtils.addOrGetModule(config, SimWrapperConfigGroup.class); + + //skip default dashboards + simwrapperCfg.defaultDashboards = SimWrapperConfigGroup.Mode.disabled; + + //add drt dashboards + new DrtDashboardProvider().getDashboards(config, sw).forEach(sw::addDashboard); + + try { + //append dashboard to existing ones + boolean append = true; + sw.generate(runDirectory, append); + sw.run(runDirectory); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + return 0; + } + + public static void main(String[] args) { + new CreateDrtDashboard().execute(args); + + } + +} diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/dashboards/DrtAnalysisPostProcessing.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/dashboards/DrtAnalysisPostProcessing.java index a8f9e8eabb0..d37eac13219 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/dashboards/DrtAnalysisPostProcessing.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/dashboards/DrtAnalysisPostProcessing.java @@ -111,7 +111,7 @@ private static Table prepareSupplyKPITable(Table vehicleStats) { .round() .setName("Total pax distance [km]")); - tableSupplyKPI.column("d_p/d_t").setName("Pooling ratio"); + tableSupplyKPI.column("d_p/d_t").setName("Occupancy rate [pax-km/v-km]"); tableSupplyKPI.column("l_det").setName("Detour ratio"); tableSupplyKPI.column("emptyRatio").setName("Empty ratio"); @@ -122,17 +122,19 @@ private static void printDemandKPICSV(Table customerStats, Table tableSupplyKPI, double rides = getLastDoubleValue(customerStats, "rides"); double rejections = getLastDoubleValue(customerStats, "rejections"); double requests = rides + rejections; + double pax = getLastDoubleValue(customerStats, "rides_pax"); DecimalFormat df = new DecimalFormat("#,###.##", new DecimalFormatSymbols(Locale.US)); try (CSVPrinter csv = new CSVPrinter(Files.newBufferedWriter(output), CSVFormat.DEFAULT)) { csv.printRecord("Info", "value"); - csv.printRecord("Requests", requests); - csv.printRecord("Rides", rides); - csv.printRecord("Rides per veh", df.format(rides / ((DoubleColumn) tableSupplyKPI.column("vehicles")).get(0))); - csv.printRecord("Rides per veh-h", df.format(rides / ((DoubleColumn) tableSupplyKPI.column("total service hours")).get(0))); - csv.printRecord("Rides per veh-km", df.format(rides / ((DoubleColumn) tableSupplyKPI.column("total vehicle mileage [km]")).get(0))); + csv.printRecord("Handled Requests", requests); + csv.printRecord("Passengers (Pax)", pax); + csv.printRecord("Avg Group Size", df.format((getLastDoubleValue(customerStats, "groupSize_mean")))); + csv.printRecord("Pax per veh", df.format(pax / ((DoubleColumn) tableSupplyKPI.column("vehicles")).get(0))); + csv.printRecord("Pax per veh-h", df.format(pax / ((DoubleColumn) tableSupplyKPI.column("total service hours")).get(0))); + csv.printRecord("Pax per veh-km", df.format(pax / ((DoubleColumn) tableSupplyKPI.column("total vehicle mileage [km]")).get(0))); csv.printRecord("Rejections", rejections); csv.printRecord("Rejection rate", getLastDoubleValue(customerStats, "rejectionRate")); csv.printRecord("Avg. total travel time", LocalTime.ofSecondOfDay(getLastDoubleValue(customerStats, "totalTravelTime_mean").longValue())); @@ -168,28 +170,13 @@ public Integer call() throws Exception { //read vehicle stats Path vehicleStatsPath = ApplicationUtils.matchInput("drt_vehicle_stats_" + drtMode + ".csv", input.getRunDirectory()); Table vehicleStats = Table.read().csv(CsvReadOptions.builder(vehicleStatsPath.toFile()) - .columnTypesPartial(Map.of("vehicles", ColumnType.DOUBLE, - "totalDistance", ColumnType.DOUBLE, - "emptyRatio", ColumnType.DOUBLE, - "totalServiceDuration", ColumnType.DOUBLE, - "d_p/d_t", ColumnType.DOUBLE, - "totalPassengerDistanceTraveled", ColumnType.DOUBLE)) + .columnTypes(columnHeader -> columnHeader.equals("runId") ? ColumnType.STRING : ColumnType.DOUBLE) .separator(';').build()); //read customer stats Path customerStatsPath = ApplicationUtils.matchInput("drt_customer_stats_" + drtMode + ".csv", input.getRunDirectory()); Table customerStats = Table.read().csv(CsvReadOptions.builder(customerStatsPath.toFile()) - .columnTypesPartial(Map.of( - "rides", ColumnType.DOUBLE, - "wait_average", ColumnType.DOUBLE, - "wait_p95", ColumnType.DOUBLE, - "inVehicleTravelTime_mean", ColumnType.DOUBLE, - "distance_m_mean", ColumnType.DOUBLE, - "directDistance_m_mean", ColumnType.DOUBLE, - "totalTravelTime_mean", ColumnType.DOUBLE, - "fareAllReferences_mean", ColumnType.DOUBLE, - "rejections", ColumnType.DOUBLE, - "rejectionRate", ColumnType.DOUBLE)) + .columnTypes(columnHeader -> columnHeader.equals("runId") ? ColumnType.STRING : ColumnType.DOUBLE) .separator(';').build()); Table tableSupplyKPI = Table.create("supplyKPI"); diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/dashboards/DrtDashboard.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/dashboards/DrtDashboard.java index b7e1aeda0f9..a62f46a1ebc 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/dashboards/DrtDashboard.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/dashboards/DrtDashboard.java @@ -386,7 +386,7 @@ public void configure(Header header, Layout layout) { .el(Line.class, (viz, data) -> { viz.title = "Relative Statistics per iteration"; viz.dataset = data.output("*vehicle_stats_" + drtConfigGroup.mode + ".csv"); - viz.description = "Pooling ratio (Pax distance / Vehicle mileage), Detour ratio, and Empty Ratio"; + viz.description = "Occupancy rate (Pax distance / Vehicle mileage), Detour ratio, and Empty Ratio"; viz.x = "iteration"; viz.columns = List.of("d_p/d_t", "l_det", "emptyRatio"); viz.legendName = List.of("Pooling ratio", "Detour ratio", "Empty Ratio"); diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/run/ShiftEDrtModeOptimizerQSimModule.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/run/ShiftEDrtModeOptimizerQSimModule.java index fdc06e3cb8b..afbf606fc1d 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/run/ShiftEDrtModeOptimizerQSimModule.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/run/ShiftEDrtModeOptimizerQSimModule.java @@ -68,7 +68,8 @@ protected void configureQSim() { bindModal(DrtShiftDispatcher.class).toProvider(modalProvider( getter -> new EDrtShiftDispatcherImpl(((EShiftTaskScheduler) getter.getModal(ShiftTaskScheduler.class)), getter.getModal(ChargingInfrastructure.class), - drtShiftParams, getter.getModal(OperationFacilities.class), new DrtShiftDispatcherImpl(getter.getModal(DrtShifts.class), getter.getModal(Fleet.class), + drtShiftParams, getter.getModal(OperationFacilities.class), new DrtShiftDispatcherImpl(getMode(), + getter.getModal(DrtShifts.class), getter.getModal(Fleet.class), getter.get(MobsimTimer.class), getter.getModal(OperationFacilities.class), getter.getModal(OperationFacilityFinder.class), getter.getModal(ShiftTaskScheduler.class), getter.getModal(Network.class), getter.get(EventsManager.class), drtShiftParams, new EDrtShiftStartLogic(new DefaultShiftStartLogic()), diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/BreakCorridorXY.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/BreakCorridorXY.java index 320b23977f9..6c4887e965e 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/BreakCorridorXY.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/BreakCorridorXY.java @@ -24,12 +24,15 @@ */ public class BreakCorridorXY implements DrtShiftBreakStartedEventHandler, DrtShiftBreakEndedEventHandler { + private final String mode; + private final Provider shifts; private final Map, Tuple> shift2plannedVsActualBreakStart = new HashMap<>(); private final Map, Tuple> shift2plannedVsActualBreakEnd = new HashMap<>(); - public BreakCorridorXY(Provider shifts) { + public BreakCorridorXY(String mode, Provider shifts) { super(); + this.mode = mode; this.shifts = shifts; reset(0); } @@ -38,16 +41,20 @@ public BreakCorridorXY(Provider shifts) { @Override public void handleEvent(DrtShiftBreakStartedEvent event) { - final DrtShiftBreakSpecification drtShiftBreak = shifts.get().getShiftSpecifications().get(event.getShiftId()).getBreak().orElseThrow(); - final double earliestBreakStartTime = drtShiftBreak.getEarliestBreakStartTime(); - shift2plannedVsActualBreakStart.put(event.getShiftId(), new Tuple<>(earliestBreakStartTime, event.getTime())); + if (event.getMode().equals(mode)) { + final DrtShiftBreakSpecification drtShiftBreak = shifts.get().getShiftSpecifications().get(event.getShiftId()).getBreak().orElseThrow(); + final double earliestBreakStartTime = drtShiftBreak.getEarliestBreakStartTime(); + shift2plannedVsActualBreakStart.put(event.getShiftId(), new Tuple<>(earliestBreakStartTime, event.getTime())); + } } @Override public void handleEvent(DrtShiftBreakEndedEvent event) { - final DrtShiftBreakSpecification drtShiftBreak = shifts.get().getShiftSpecifications().get(event.getShiftId()).getBreak().orElseThrow(); - final double latestBreakEndTime = drtShiftBreak.getLatestBreakEndTime(); - shift2plannedVsActualBreakEnd.put(event.getShiftId(), new Tuple<>(latestBreakEndTime, event.getTime())); + if (event.getMode().equals(mode)) { + final DrtShiftBreakSpecification drtShiftBreak = shifts.get().getShiftSpecifications().get(event.getShiftId()).getBreak().orElseThrow(); + final double latestBreakEndTime = drtShiftBreak.getLatestBreakEndTime(); + shift2plannedVsActualBreakEnd.put(event.getShiftId(), new Tuple<>(latestBreakEndTime, event.getTime())); + } } @Override diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/ShiftDurationXY.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/ShiftDurationXY.java index d2ff4dda184..809e4385323 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/ShiftDurationXY.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/ShiftDurationXY.java @@ -30,9 +30,12 @@ public class ShiftDurationXY implements DrtShiftStartedEventHandler, DrtShiftEnd private final Map, Tuple> shift2plannedVsActualDuration = new HashMap<>(); private final Map, Tuple> shift2plannedVsActualBreakDuration = new HashMap<>(); - public ShiftDurationXY(Provider shifts) { + private final String mode; + + public ShiftDurationXY(Provider shifts, String mode) { super(); this.shifts = shifts; + this.mode = mode; reset(0); } @@ -40,30 +43,38 @@ public ShiftDurationXY(Provider shifts) { @Override public void handleEvent(final DrtShiftStartedEvent event) { - shift2StartTime.put(event.getShiftId(), event.getTime()); + if (event.getMode().equals(mode)) { + shift2StartTime.put(event.getShiftId(), event.getTime()); + } } @Override public void handleEvent(DrtShiftBreakStartedEvent event) { - shift2BreakStartTime.put(event.getShiftId(), event.getTime()); + if (event.getMode().equals(mode)) { + shift2BreakStartTime.put(event.getShiftId(), event.getTime()); + } } @Override public void handleEvent(final DrtShiftEndedEvent event) { - final Double start = shift2StartTime.get(event.getShiftId()); - double duration = event.getTime() - start; - final DrtShiftSpecification drtShift = shifts.get().getShiftSpecifications().get(event.getShiftId()); - double plannedDuration = drtShift.getEndTime() - drtShift.getStartTime(); - shift2plannedVsActualDuration.put(event.getShiftId(), new Tuple<>(plannedDuration, duration)); + if (event.getMode().equals(mode)) { + final Double start = shift2StartTime.get(event.getShiftId()); + double duration = event.getTime() - start; + final DrtShiftSpecification drtShift = shifts.get().getShiftSpecifications().get(event.getShiftId()); + double plannedDuration = drtShift.getEndTime() - drtShift.getStartTime(); + shift2plannedVsActualDuration.put(event.getShiftId(), new Tuple<>(plannedDuration, duration)); + } } @Override public void handleEvent(DrtShiftBreakEndedEvent event) { - final Double start = shift2BreakStartTime.get(event.getShiftId()); - double duration = event.getTime() - start; - final DrtShiftBreakSpecification drtShift = shifts.get().getShiftSpecifications().get(event.getShiftId()).getBreak().orElseThrow(); - double plannedDuration = drtShift.getDuration(); - shift2plannedVsActualBreakDuration.put(event.getShiftId(), new Tuple<>(plannedDuration, duration)); + if (event.getMode().equals(mode)) { + final Double start = shift2BreakStartTime.get(event.getShiftId()); + double duration = event.getTime() - start; + final DrtShiftBreakSpecification drtShift = shifts.get().getShiftSpecifications().get(event.getShiftId()).getBreak().orElseThrow(); + double plannedDuration = drtShift.getDuration(); + shift2plannedVsActualBreakDuration.put(event.getShiftId(), new Tuple<>(plannedDuration, duration)); + } } @Override diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/ShiftHistogram.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/ShiftHistogram.java index ce228469e50..00dc4e85a02 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/ShiftHistogram.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/ShiftHistogram.java @@ -20,6 +20,8 @@ public class ShiftHistogram implements DrtShiftStartedEventHandler, DrtShiftEndedEventHandler, DrtShiftBreakStartedEventHandler, DrtShiftBreakEndedEventHandler { + private final String mode; + public static final int DEFAULT_END_TIME = 30 * 3600; public static final int DEFAULT_BIN_SIZE = 300; @@ -30,9 +32,10 @@ public class ShiftHistogram implements DrtShiftStartedEventHandler, DrtShiftEnde private DataFrame data = null; - public ShiftHistogram(Population population, Config config) { + public ShiftHistogram(Population population, String mode, Config config) { super(); - this.binSize = DEFAULT_BIN_SIZE; + this.mode = mode; + this.binSize = DEFAULT_BIN_SIZE; this.nofBins = ((int) config.qsim().getEndTime().orElse(DEFAULT_END_TIME) ) / this.binSize + 1; reset(0); if (population == null) { @@ -46,8 +49,9 @@ public ShiftHistogram(Population population, Config config) { * @param binSize The size of a time bin in seconds. * @param nofBins The number of time bins for this analysis. */ - public ShiftHistogram(final int binSize, final int nofBins) { + public ShiftHistogram(String mode, final int binSize, final int nofBins) { super(); + this.mode = mode; this.binSize = binSize; this.nofBins = nofBins; reset(0); @@ -57,34 +61,42 @@ public ShiftHistogram(final int binSize, final int nofBins) { @Override public void handleEvent(final DrtShiftStartedEvent event) { - int index = getBinIndex(event.getTime()); - if ((this.shiftIds == null || this.shiftIds.contains(event.getShiftId()))) { - DataFrame dataFrame = getData(); - dataFrame.countsStart[index]++; + if (event.getMode().equals(mode)) { + int index = getBinIndex(event.getTime()); + if ((this.shiftIds == null || this.shiftIds.contains(event.getShiftId()))) { + DataFrame dataFrame = getData(); + dataFrame.countsStart[index]++; + } } } @Override public void handleEvent(final DrtShiftEndedEvent event) { - int index = getBinIndex(event.getTime()); - if ((this.shiftIds == null || this.shiftIds.contains(event.getShiftId()))) { - DataFrame dataFrame = getData(); - dataFrame.countsEnd[index]++; + if (event.getMode().equals(mode)) { + int index = getBinIndex(event.getTime()); + if ((this.shiftIds == null || this.shiftIds.contains(event.getShiftId()))) { + DataFrame dataFrame = getData(); + dataFrame.countsEnd[index]++; + } } } @Override public void handleEvent(DrtShiftBreakStartedEvent event) { - int index = getBinIndex(event.getTime()); - DataFrame dataFrame = getData(); - dataFrame.countsBreaksStart[index]++; + if (event.getMode().equals(mode)) { + int index = getBinIndex(event.getTime()); + DataFrame dataFrame = getData(); + dataFrame.countsBreaksStart[index]++; + } } @Override public void handleEvent(DrtShiftBreakEndedEvent event) { - int index = getBinIndex(event.getTime()); - DataFrame dataFrame = getData(); - dataFrame.countsBreaksEnd[index]++; + if (event.getMode().equals(mode)) { + int index = getBinIndex(event.getTime()); + DataFrame dataFrame = getData(); + dataFrame.countsBreaksEnd[index]++; + } } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/efficiency/DrtShiftEfficiencyModeModule.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/efficiency/DrtShiftEfficiencyModeModule.java index e339db2fb30..d8f4db9f33e 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/efficiency/DrtShiftEfficiencyModeModule.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/efficiency/DrtShiftEfficiencyModeModule.java @@ -31,7 +31,7 @@ public DrtShiftEfficiencyModeModule(DrtConfigGroup drtConfigGroup) { @Override public void install() { bindModal(ShiftEfficiencyTracker.class).toProvider(modalProvider(getter -> - new ShiftEfficiencyTracker())).asEagerSingleton(); + new ShiftEfficiencyTracker(getMode()))).asEagerSingleton(); addEventHandlerBinding().to(modalKey(ShiftEfficiencyTracker.class)); bindModal(ShiftEfficiencyAnalysisControlerListener.class).toProvider(modalProvider(getter -> new ShiftEfficiencyAnalysisControlerListener(drtConfigGroup, diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/efficiency/ShiftEfficiencyTracker.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/efficiency/ShiftEfficiencyTracker.java index 7ccb1edbbfc..c7963f13ca5 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/efficiency/ShiftEfficiencyTracker.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/efficiency/ShiftEfficiencyTracker.java @@ -37,6 +37,7 @@ public final class ShiftEfficiencyTracker implements PersonMoneyEventHandler, PassengerDroppedOffEventHandler, DrtShiftStartedEventHandler, DrtShiftEndedEventHandler { + private final String mode; private Map, Double> revenueByShift; private Map, Id> shiftByRequest; @@ -63,8 +64,9 @@ public Map, Id> getFinishedShifts() { } } - public ShiftEfficiencyTracker() { - this.revenueByShift = new HashMap<>(); + public ShiftEfficiencyTracker(String mode) { + this.mode = mode; + this.revenueByShift = new HashMap<>(); this.shiftByRequest = new HashMap<>(); this.finishedShifts = new HashMap<>(); this.currentRecord = new Record(revenueByShift, shiftByRequest, finishedShifts); @@ -72,35 +74,43 @@ public ShiftEfficiencyTracker() { @Override public void handleEvent(PersonMoneyEvent personMoneyEvent) { - if (DrtFareHandler.PERSON_MONEY_EVENT_PURPOSE_DRT_FARE.equals(personMoneyEvent.getPurpose())) { - Id key = shiftByRequest.get(Id.create(personMoneyEvent.getReference(), DrtRequest.class)); - if(key != null) { - revenueByShift.merge(key, -personMoneyEvent.getAmount(), Double::sum); + if(personMoneyEvent.getTransactionPartner().equals(mode)) { + if (DrtFareHandler.PERSON_MONEY_EVENT_PURPOSE_DRT_FARE.equals(personMoneyEvent.getPurpose())) { + Id key = shiftByRequest.get(Id.create(personMoneyEvent.getReference(), DrtRequest.class)); + if (key != null) { + revenueByShift.merge(key, -personMoneyEvent.getAmount(), Double::sum); + } } } } @Override public void handleEvent(PassengerDroppedOffEvent event) { - Id vehicleId = event.getVehicleId(); - Gbl.assertIf(activeShifts.containsKey(vehicleId)); - Id drtShiftId = activeShifts.get(vehicleId); - shiftByRequest.put(event.getRequestId(), drtShiftId); + if(event.getMode().equals(mode)) { + Id vehicleId = event.getVehicleId(); + Gbl.assertIf(activeShifts.containsKey(vehicleId)); + Id drtShiftId = activeShifts.get(vehicleId); + shiftByRequest.put(event.getRequestId(), drtShiftId); + } } @Override public void handleEvent(DrtShiftStartedEvent event) { - revenueByShift.put(event.getShiftId(), 0.); - if(activeShifts.containsKey(event.getVehicleId())) { - throw new RuntimeException("Vehicle is already registered for another shift"); + if(event.getMode().equals(mode)) { + revenueByShift.put(event.getShiftId(), 0.); + if (activeShifts.containsKey(event.getVehicleId())) { + throw new RuntimeException("Vehicle is already registered for another shift"); + } + activeShifts.put(event.getVehicleId(), event.getShiftId()); } - activeShifts.put(event.getVehicleId(), event.getShiftId()); } @Override public void handleEvent(DrtShiftEndedEvent event) { - activeShifts.remove(event.getVehicleId()); - finishedShifts.put(event.getShiftId(), event.getVehicleId()); + if(event.getMode().equals(mode)) { + activeShifts.remove(event.getVehicleId()); + finishedShifts.put(event.getShiftId(), event.getVehicleId()); + } } @Override diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java index 4c070bc1ebf..c32b5d1b12b 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java @@ -49,6 +49,8 @@ public class DrtShiftDispatcherImpl implements DrtShiftDispatcher { private final static Logger logger = LogManager.getLogger(DrtShiftDispatcherImpl.class); + private final String mode; + private Queue unscheduledShifts; private Queue assignedShifts; private Queue activeShifts; @@ -74,10 +76,11 @@ public class DrtShiftDispatcherImpl implements DrtShiftDispatcher { private final ShiftStartLogic shiftStartLogic; private final AssignShiftToVehicleLogic assignShiftToVehicleLogic; - public DrtShiftDispatcherImpl(DrtShifts shifts, Fleet fleet, MobsimTimer timer, OperationFacilities operationFacilities, - OperationFacilityFinder breakFacilityFinder, ShiftTaskScheduler shiftTaskScheduler, - Network network, EventsManager eventsManager, ShiftsParams drtShiftParams, - ShiftStartLogic shiftStartLogic, AssignShiftToVehicleLogic assignShiftToVehicleLogic) { + public DrtShiftDispatcherImpl(String mode, DrtShifts shifts, Fleet fleet, MobsimTimer timer, OperationFacilities operationFacilities, + OperationFacilityFinder breakFacilityFinder, ShiftTaskScheduler shiftTaskScheduler, + Network network, EventsManager eventsManager, ShiftsParams drtShiftParams, + ShiftStartLogic shiftStartLogic, AssignShiftToVehicleLogic assignShiftToVehicleLogic) { + this.mode = mode; this.shifts = shifts; this.fleet = fleet; this.timer = timer; @@ -140,7 +143,7 @@ private void checkBreaks() { OperationFacility breakFacility = decideOnBreak(activeShift); if (breakFacility != null) { shiftTaskScheduler.relocateForBreak(activeShift.vehicle(), breakFacility, shift); - eventsManager.processEvent(new DrtShiftBreakScheduledEvent(timer.getTimeOfDay(), shift.getId(), + eventsManager.processEvent(new DrtShiftBreakScheduledEvent(timer.getTimeOfDay(), mode, shift.getId(), activeShift.vehicle().getId(), breakFacility.getLinkId(), shift.getBreak().orElseThrow().getScheduledLatestArrival())); } @@ -169,7 +172,7 @@ private void startShifts(double timeStep) { iterator.remove(); logger.debug("Started shift " + next.shift()); StayTask currentTask = (StayTask) next.vehicle().getSchedule().getCurrentTask(); - eventsManager.processEvent(new DrtShiftStartedEvent(timeStep, next.shift().getId(), next.vehicle().getId(), + eventsManager.processEvent(new DrtShiftStartedEvent(timeStep, mode, next.shift().getId(), next.vehicle().getId(), currentTask.getLink().getId())); } } @@ -262,7 +265,7 @@ private void assignShiftToVehicle(DrtShift shift, ShiftDvrpVehicle vehicle) { Gbl.assertNotNull(vehicle); vehicle.addShift(shift); assignedShifts.add(new ShiftEntry(shift, vehicle)); - eventsManager.processEvent(new DrtShiftAssignedEvent(timer.getTimeOfDay(), shift.getId(), vehicle.getId())); + eventsManager.processEvent(new DrtShiftAssignedEvent(timer.getTimeOfDay(), mode, shift.getId(), vehicle.getId())); } private void endShifts(double timeStep) { @@ -370,7 +373,7 @@ private void updateShiftEnd(ShiftEntry next) { shiftChangeFacility.register(next.vehicle().getId()); changeOverTask.getFacility().deregisterVehicle(next.vehicle().getId()); eventsManager.processEvent(new ShiftFacilityRegistrationEvent(timer.getTimeOfDay(), - next.vehicle().getId(), shiftChangeFacility.getId())); + mode, next.vehicle().getId(), shiftChangeFacility.getId())); } } } @@ -426,7 +429,7 @@ private void scheduleShiftEnd(ShiftEntry endingShift) { if (shiftChangeoverFacility != null && shiftChangeoverFacility.register(endingShift.vehicle().getId())) { shiftTaskScheduler.relocateForShiftChange(endingShift.vehicle(), network.getLinks().get(shiftChangeoverFacility.getLinkId()), endingShift.shift(), shiftChangeoverFacility); - eventsManager.processEvent(new ShiftFacilityRegistrationEvent(timer.getTimeOfDay(), endingShift.vehicle().getId(), + eventsManager.processEvent(new ShiftFacilityRegistrationEvent(timer.getTimeOfDay(), mode, endingShift.vehicle().getId(), shiftChangeoverFacility.getId())); } else { throw new RuntimeException("Could not find shift end location!"); @@ -458,7 +461,7 @@ private OperationFacility decideOnBreak(ShiftEntry activeShift) { } if (shiftBreakFacility.register(activeShift.vehicle().getId())) { eventsManager.processEvent(new ShiftFacilityRegistrationEvent(timer.getTimeOfDay(), - activeShift.vehicle().getId(), shiftBreakFacility.getId())); + mode, activeShift.vehicle().getId(), shiftBreakFacility.getId())); return shiftBreakFacility; } } @@ -471,7 +474,7 @@ public void endShift(ShiftDvrpVehicle vehicle, Id id, Id linkId) { - eventsManager.processEvent(new DrtShiftBreakStartedEvent(timer.getTimeOfDay(), vehicle.getShifts().peek().getId(), vehicle.getId(), linkId)); + eventsManager.processEvent( + new DrtShiftBreakStartedEvent(timer.getTimeOfDay(), mode, + vehicle.getShifts().peek().getId(), vehicle.getId(), linkId) + ); } private boolean isSchedulable(DrtShift shift, double timeStep) { diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/AbstractShiftEvent.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/AbstractShiftEvent.java new file mode 100644 index 00000000000..8627017c565 --- /dev/null +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/AbstractShiftEvent.java @@ -0,0 +1,43 @@ +package org.matsim.contrib.drt.extension.operations.shifts.events; + +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.events.Event; +import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShift; + +import java.util.Map; + +/** + * @author nkuehnel / MOIA + */ +public abstract class AbstractShiftEvent extends Event { + + public static final String ATTRIBUTE_MODE = "mode"; + private final Id shiftId; + + public static final String ATTRIBUTE_SHIFT_ID = "shift_id"; + + + private final String mode; + + public AbstractShiftEvent(double time, String mode, Id id) { + super(time); + this.mode = mode; + shiftId = id; + } + + public String getMode() { + return mode; + } + + public Id getShiftId() { + return shiftId; + } + + @Override + public Map getAttributes() { + Map attr = super.getAttributes(); + attr.put(ATTRIBUTE_MODE, mode); + attr.put(ATTRIBUTE_SHIFT_ID, shiftId + ""); + return attr; + } +} diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/DrtShiftAssignedEvent.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/DrtShiftAssignedEvent.java index 29678467dd1..b867f305a83 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/DrtShiftAssignedEvent.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/DrtShiftAssignedEvent.java @@ -10,20 +10,18 @@ /** * @author nkuehnel / MOIA */ -public class DrtShiftAssignedEvent extends Event { +public class DrtShiftAssignedEvent extends AbstractShiftEvent { + - private final Id shiftId; private final Id vehicleId; - public static final String ATTRIBUTE_SHIFT_ID = "id"; public static final String ATTRIBUTE_VEHICLE_ID = "vehicle"; public static final String EVENT_TYPE = "DRT shift assigned"; - public DrtShiftAssignedEvent(double timeOfDay, Id id, Id id1) { - super(timeOfDay); - shiftId = id; - vehicleId = id1; + public DrtShiftAssignedEvent(double timeOfDay, String mode, Id shiftId, Id vehicleId) { + super(timeOfDay, mode, shiftId); + this.vehicleId = vehicleId; } @Override @@ -34,7 +32,6 @@ public String getEventType() { @Override public Map getAttributes() { Map attr = super.getAttributes(); - attr.put(ATTRIBUTE_SHIFT_ID, shiftId + ""); attr.put(ATTRIBUTE_VEHICLE_ID, vehicleId + ""); return attr; } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/DrtShiftBreakEndedEvent.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/DrtShiftBreakEndedEvent.java index 1bad8287e06..1881907b00e 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/DrtShiftBreakEndedEvent.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/DrtShiftBreakEndedEvent.java @@ -11,28 +11,22 @@ /** * @author nkuehnel / MOIA */ -public class DrtShiftBreakEndedEvent extends Event { +public class DrtShiftBreakEndedEvent extends AbstractShiftEvent { - private final Id shiftId; private final Id vehicleId; private final Id linkId; public static final String ATTRIBUTE_LINK = "link"; - public static final String ATTRIBUTE_SHIFT_ID = "id"; public static final String ATTRIBUTE_VEHICLE_ID = "vehicle"; public static final String EVENT_TYPE = "DRT shift break ended"; - public DrtShiftBreakEndedEvent(double time, Id shiftId, Id vehicleId, Id linkId) { - super(time); - this.shiftId = shiftId; + public DrtShiftBreakEndedEvent(double time, String mode, Id shiftId, Id vehicleId, Id linkId) { + super(time, mode, shiftId); this.vehicleId = vehicleId; this.linkId = linkId; } - public Id getShiftId() { - return shiftId; - } public Id getVehicleId() { return vehicleId; @@ -50,7 +44,6 @@ public String getEventType() { @Override public Map getAttributes() { Map attr = super.getAttributes(); - attr.put(ATTRIBUTE_SHIFT_ID, shiftId + ""); attr.put(ATTRIBUTE_VEHICLE_ID, vehicleId + ""); attr.put(ATTRIBUTE_LINK, linkId + ""); return attr; diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/DrtShiftBreakScheduledEvent.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/DrtShiftBreakScheduledEvent.java index 3e1ac8189dc..c734b5d4078 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/DrtShiftBreakScheduledEvent.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/DrtShiftBreakScheduledEvent.java @@ -11,9 +11,8 @@ /** * @author nkuehnel / MOIA */ -public class DrtShiftBreakScheduledEvent extends Event { +public class DrtShiftBreakScheduledEvent extends AbstractShiftEvent { - private final Id shiftId; private final Id vehicleId; private final Id linkId; private final double latestArrival; @@ -25,10 +24,9 @@ public class DrtShiftBreakScheduledEvent extends Event { public static final String EVENT_TYPE = "DRT shift break scheduled"; - public DrtShiftBreakScheduledEvent(double timeOfDay, Id id, Id id1, Id linkId, double latestArrival) { - super(timeOfDay); - shiftId = id; - vehicleId = id1; + public DrtShiftBreakScheduledEvent(double timeOfDay, String mode, Id shiftId, Id vehicleId, Id linkId, double latestArrival) { + super(timeOfDay, mode, shiftId); + this.vehicleId = vehicleId; this.linkId = linkId; this.latestArrival = latestArrival; } @@ -41,7 +39,6 @@ public String getEventType() { @Override public Map getAttributes() { Map attr = super.getAttributes(); - attr.put(ATTRIBUTE_SHIFT_ID, shiftId + ""); attr.put(ATTRIBUTE_VEHICLE_ID, vehicleId + ""); attr.put(ATTRIBUTE_LINK_ID, linkId + ""); attr.put(ATTRIBUTE_LATEST_ARRIVAL, latestArrival + ""); diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/DrtShiftBreakStartedEvent.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/DrtShiftBreakStartedEvent.java index a089c150375..22a9a4e7854 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/DrtShiftBreakStartedEvent.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/DrtShiftBreakStartedEvent.java @@ -11,9 +11,8 @@ /** * @author nkuehnel / MOIA */ -public class DrtShiftBreakStartedEvent extends Event { +public class DrtShiftBreakStartedEvent extends AbstractShiftEvent { - private final Id shiftId; private final Id vehicleId; private final Id linkId; @@ -23,16 +22,12 @@ public class DrtShiftBreakStartedEvent extends Event { public static final String EVENT_TYPE = "DRT shift break started"; - public DrtShiftBreakStartedEvent(double time, Id shiftId, Id vehicleId, Id linkId) { - super(time); - this.shiftId = shiftId; + public DrtShiftBreakStartedEvent(double time, String mode, Id shiftId, Id vehicleId, Id linkId) { + super(time, mode, shiftId); this.vehicleId = vehicleId; this.linkId = linkId; } - public Id getShiftId() { - return shiftId; - } public Id getVehicleId() { return vehicleId; @@ -50,7 +45,6 @@ public String getEventType() { @Override public Map getAttributes() { Map attr = super.getAttributes(); - attr.put(ATTRIBUTE_SHIFT_ID, shiftId + ""); attr.put(ATTRIBUTE_VEHICLE_ID, vehicleId + ""); attr.put(ATTRIBUTE_LINK, linkId + ""); return attr; diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/DrtShiftEndedEvent.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/DrtShiftEndedEvent.java index 98f584f2fd0..2794a123314 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/DrtShiftEndedEvent.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/DrtShiftEndedEvent.java @@ -12,9 +12,8 @@ /** * @author nkuehnel / MOIA */ -public class DrtShiftEndedEvent extends Event { +public class DrtShiftEndedEvent extends AbstractShiftEvent { - private final Id shiftId; private final Id vehicleId; private final Id linkId; private final Id operationFacilityId; @@ -26,18 +25,14 @@ public class DrtShiftEndedEvent extends Event { public static final String EVENT_TYPE = "DRT shift ended"; - public DrtShiftEndedEvent(double time, Id shiftId, Id vehicleId, - Id linkId, Id operationFacilityId) { - super(time); - this.shiftId = shiftId; + public DrtShiftEndedEvent(double time, String mode, Id shiftId, Id vehicleId, + Id linkId, Id operationFacilityId) { + super(time, mode, shiftId); this.vehicleId = vehicleId; this.linkId = linkId; this.operationFacilityId = operationFacilityId; } - public Id getShiftId() { - return shiftId; - } public Id getVehicleId() { return vehicleId; @@ -59,7 +54,6 @@ public String getEventType() { @Override public Map getAttributes() { Map attr = super.getAttributes(); - attr.put(ATTRIBUTE_SHIFT_ID, shiftId + ""); attr.put(ATTRIBUTE_VEHICLE_ID, vehicleId + ""); attr.put(ATTRIBUTE_LINK, linkId + ""); attr.put(ATTRIBUTE_OPERATION_FACILITY, operationFacilityId + ""); diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/DrtShiftStartedEvent.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/DrtShiftStartedEvent.java index 4f49d8610dc..9b2d1a0da2c 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/DrtShiftStartedEvent.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/DrtShiftStartedEvent.java @@ -11,9 +11,8 @@ /** * @author nkuehnel / MOIA */ -public class DrtShiftStartedEvent extends Event { +public class DrtShiftStartedEvent extends AbstractShiftEvent { - private final Id shiftId; private final Id vehicleId; private final Id linkId; @@ -23,17 +22,12 @@ public class DrtShiftStartedEvent extends Event { public static final String EVENT_TYPE = "DRT shift started"; - public DrtShiftStartedEvent(double time, Id shiftId, Id vehicleId, Id linkId) { - super(time); - this.shiftId = shiftId; + public DrtShiftStartedEvent(double time, String mode, Id shiftId, Id vehicleId, Id linkId) { + super(time, mode, shiftId); this.vehicleId = vehicleId; this.linkId = linkId; } - public Id getShiftId() { - return shiftId; - } - public Id getVehicleId() { return vehicleId; } @@ -50,7 +44,6 @@ public String getEventType() { @Override public Map getAttributes() { Map attr = super.getAttributes(); - attr.put(ATTRIBUTE_SHIFT_ID, shiftId + ""); attr.put(ATTRIBUTE_VEHICLE_ID, vehicleId + ""); attr.put(ATTRIBUTE_LINK, linkId + ""); return attr; diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/ShiftFacilityRegistrationEvent.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/ShiftFacilityRegistrationEvent.java index 8e6d5cb5f22..237eeca279f 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/ShiftFacilityRegistrationEvent.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/ShiftFacilityRegistrationEvent.java @@ -12,20 +12,28 @@ */ public class ShiftFacilityRegistrationEvent extends Event { + private final String mode; private final Id vehicleId; private final Id facilityId; + public static final String ATTRIBUTE_MODE = "mode"; + public static final String ATTRIBUTE_FACILITY = "facility"; public static final String ATTRIBUTE_VEHICLE_ID = "vehicle"; public static final String EVENT_TYPE = "Vehicle registered at shift facility"; - public ShiftFacilityRegistrationEvent(double time, Id vehicleId, Id facilityId) { + public ShiftFacilityRegistrationEvent(double time, String mode, Id vehicleId, Id facilityId) { super(time); + this.mode = mode; this.facilityId = facilityId; this.vehicleId = vehicleId; } + public String getMode() { + return mode; + } + @Override public String getEventType() { return EVENT_TYPE; @@ -34,6 +42,7 @@ public String getEventType() { @Override public Map getAttributes() { Map attr = super.getAttributes(); + attr.put(ATTRIBUTE_MODE, mode); attr.put(ATTRIBUTE_VEHICLE_ID, vehicleId + ""); attr.put(ATTRIBUTE_FACILITY, facilityId + ""); return attr; diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/VehicleLeftShiftFacilityEvent.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/VehicleLeftShiftFacilityEvent.java index bc141818ddc..a9742c45bf9 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/VehicleLeftShiftFacilityEvent.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/events/VehicleLeftShiftFacilityEvent.java @@ -12,16 +12,20 @@ */ public class VehicleLeftShiftFacilityEvent extends Event { + private final String mode; private final Id vehicleId; private final Id facilityId; + public static final String ATTRIBUTE_MODE = "mode"; + public static final String ATTRIBUTE_FACILITY = "facility"; public static final String ATTRIBUTE_VEHICLE_ID = "vehicle"; public static final String EVENT_TYPE = "Vehicle left shift facility"; - public VehicleLeftShiftFacilityEvent(double time, Id vehicleId, Id facilityId) { + public VehicleLeftShiftFacilityEvent(double time, String mode, Id vehicleId, Id facilityId) { super(time); + this.mode = mode; this.facilityId = facilityId; this.vehicleId = vehicleId; } @@ -34,6 +38,7 @@ public String getEventType() { @Override public Map getAttributes() { Map attr = super.getAttributes(); + attr.put(ATTRIBUTE_MODE, mode); attr.put(ATTRIBUTE_VEHICLE_ID, vehicleId + ""); attr.put(ATTRIBUTE_FACILITY, facilityId + ""); return attr; diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeModule.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeModule.java index 5005c8227c9..91e324456d1 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeModule.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeModule.java @@ -91,15 +91,15 @@ public void install() { } bindModal(ShiftDurationXY.class).toProvider(modalProvider( - getter -> new ShiftDurationXY(getter.getModal(new TypeLiteral>(){})) + getter -> new ShiftDurationXY(getter.getModal(new TypeLiteral>(){}), getMode()) )).asEagerSingleton(); bindModal(BreakCorridorXY.class).toProvider(modalProvider( - getter -> new BreakCorridorXY(getter.getModal(new TypeLiteral>(){})) + getter -> new BreakCorridorXY(getMode(), getter.getModal(new TypeLiteral>(){})) )).asEagerSingleton(); bindModal(ShiftHistogram.class).toProvider(modalProvider( - getter -> new ShiftHistogram(getter.get(Population.class), getter.get(Config.class)))).asEagerSingleton(); + getter -> new ShiftHistogram(getter.get(Population.class), getMode(), getter.get(Config.class)))).asEagerSingleton(); addEventHandlerBinding().to(modalKey(ShiftDurationXY.class)); addEventHandlerBinding().to(modalKey(BreakCorridorXY.class)); diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeOptimizerQSimModule.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeOptimizerQSimModule.java index 5fbae488eec..a10c6e409e3 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeOptimizerQSimModule.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeOptimizerQSimModule.java @@ -113,7 +113,7 @@ public DrtShifts get() { })); bindModal(DrtShiftDispatcher.class).toProvider(modalProvider( - getter -> new DrtShiftDispatcherImpl(getter.getModal(DrtShifts.class), getter.getModal(Fleet.class), + getter -> new DrtShiftDispatcherImpl(getMode(), getter.getModal(DrtShifts.class), getter.getModal(Fleet.class), getter.get(MobsimTimer.class), getter.getModal(OperationFacilities.class), getter.getModal(OperationFacilityFinder.class), getter.getModal(ShiftTaskScheduler.class), getter.getModal(Network.class), getter.get(EventsManager.class), shiftsParams, new DefaultShiftStartLogic(), new DefaultAssignShiftToVehicleLogic(shiftsParams))) diff --git a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/efficiency/ShiftEfficiencyTest.java b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/efficiency/ShiftEfficiencyTest.java index b3e8db5e38d..0679adaefb8 100644 --- a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/efficiency/ShiftEfficiencyTest.java +++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/analysis/efficiency/ShiftEfficiencyTest.java @@ -41,7 +41,7 @@ public class ShiftEfficiencyTest { void testDrtShiftEfficiency() { EventsManager events = new EventsManagerImpl(); - ShiftEfficiencyTracker shiftEfficiencyTracker = new ShiftEfficiencyTracker(); + ShiftEfficiencyTracker shiftEfficiencyTracker = new ShiftEfficiencyTracker("drt"); events.addHandler(shiftEfficiencyTracker); events.initProcessing(); @@ -50,11 +50,11 @@ void testDrtShiftEfficiency() { Id vehicle1 = Id.create("vehicle1", DvrpVehicle.class); Id operationFacility1 = Id.create("operationFacility1", OperationFacility.class); - events.processEvent(new DrtShiftStartedEvent(10 * 3600, shift1, vehicle1, link1) + events.processEvent(new DrtShiftStartedEvent(10 * 3600, "drt", shift1, vehicle1, link1) ); // should throw because vehicle is already registered with another shift Assertions.assertThrows(RuntimeException.class, () -> { - events.processEvent(new DrtShiftStartedEvent(10 * 3600, shift1, vehicle1, link1)); + events.processEvent(new DrtShiftStartedEvent(10 * 3600, "drt", shift1, vehicle1, link1)); }); Id request1 = Id.create("request1", Request.class); @@ -69,7 +69,7 @@ void testDrtShiftEfficiency() { Assertions.assertEquals(FARE, shiftEfficiencyTracker.getCurrentRecord().getRevenueByShift().get(shift1), MatsimTestUtils.EPSILON); Assertions.assertFalse(shiftEfficiencyTracker.getCurrentRecord().getFinishedShifts().containsKey(shift1)); - events.processEvent(new DrtShiftEndedEvent(20 * 3600, shift1, vehicle1, link1, operationFacility1)); + events.processEvent(new DrtShiftEndedEvent(20 * 3600, "drt", shift1, vehicle1, link1, operationFacility1)); Assertions.assertTrue(shiftEfficiencyTracker.getCurrentRecord().getFinishedShifts().containsKey(shift1)); } } diff --git a/contribs/simwrapper/src/test/java/org/matsim/simwrapper/dashboard/NoiseDashboardTests.java b/contribs/simwrapper/src/test/java/org/matsim/simwrapper/dashboard/NoiseDashboardTests.java index 58c3182b5ba..6ca2a08cee3 100644 --- a/contribs/simwrapper/src/test/java/org/matsim/simwrapper/dashboard/NoiseDashboardTests.java +++ b/contribs/simwrapper/src/test/java/org/matsim/simwrapper/dashboard/NoiseDashboardTests.java @@ -1,5 +1,6 @@ package org.matsim.simwrapper.dashboard; +import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import org.matsim.application.MATSimApplication; @@ -15,6 +16,7 @@ import java.net.URL; +import java.nio.file.Path; public class NoiseDashboardTests { @@ -24,6 +26,8 @@ public class NoiseDashboardTests { @Test void generate() { + Path out = Path.of(utils.getOutputDirectory(), "analysis", "noise"); + Config config = TestScenario.loadConfig(utils); config.global().setCoordinateSystem("EPSG:25832"); @@ -34,11 +38,14 @@ void generate() { simWrapperConfigGroup.defaultParams().shp = IOUtils.extendUrl(kelheim, "area/area.shp").toString(); - SimWrapper sw = SimWrapper.create(config).addDashboard(new NoiseDashboard()); Controler controler = MATSimApplication.prepare(new TestScenario(sw), config); - controler.run(); + + Assertions.assertThat(out) + .isDirectoryContaining("glob:**emission_per_day.csv") + .isDirectoryContaining("glob:**immission_per_day.avro") + .isDirectoryContaining("glob:**immission_per_hour.avro"); } } diff --git a/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorCore.java b/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorCore.java index 4a84ee50c21..3778eebfaea 100644 --- a/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorCore.java +++ b/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorCore.java @@ -168,6 +168,10 @@ public RaptorRoute calcLeastCostRoute(double depTime, Facility fromFacility, Fac // if it's intermodal, we still start here, as we might transfer to another close-by but non-intermodal stop. continue; } + if (!routeStop.routeStop.isAllowBoarding()) { + continue; + } + RRoute route = this.data.routes[routeStop.transitRouteIndex]; int depOffset = routeStop.departureOffset; @@ -318,6 +322,9 @@ public List calcRoutes(double earliestDepTime, double desiredDepTim // this is the last stop of a route continue; } + if (!routeStop.routeStop.isAllowBoarding()) { + continue; + } RRoute route = this.data.routes[routeStop.transitRouteIndex]; int depOffset = routeStop.departureOffset; for (int depIndex = route.indexFirstDeparture; depIndex < route.indexFirstDeparture + route.countDepartures; depIndex++) { @@ -502,13 +509,15 @@ public Map, TravelInfo> calcLeastCostTree(double depTime int[] routeStopIndices = this.data.routeStopsPerStopFacility.get(stop.stop); for (int routeStopIndex : routeStopIndices) { boolean useStop = true; - if (parameters.isExactDeparturesOnly()) { - RRouteStop routeStop = this.data.routeStops[routeStopIndex]; + RRouteStop routeStop = this.data.routeStops[routeStopIndex]; + if (!routeStop.routeStop.isAllowBoarding()) { + useStop = false; + } + if (useStop && parameters.isExactDeparturesOnly()) { int routeIndex = routeStop.transitRouteIndex; RRoute route = this.data.routes[routeIndex]; int currentDepartureIndex = findNextDepartureIndex(route, routeStop, (int) depTime); if (currentDepartureIndex >= 0) { - Vehicle currentVehicle = this.data.departureVehicles[currentDepartureIndex]; int firstDepartureTime = this.data.departures[currentDepartureIndex]; int stopDepartureTime = firstDepartureTime + routeStop.departureOffset; useStop = Math.abs(depTime - stopDepartureTime) < 1e-5; @@ -692,8 +701,11 @@ private void exploreRoutes(RaptorParameters parameters, Person person, CachingTr transferProvider.reset(boardingPE.transfer); for (int toRouteStopIndex = firstRouteStopIndex + 1; toRouteStopIndex < route.indexFirstRouteStop + route.countRouteStops; toRouteStopIndex++) { - routeSegmentIterator.reset(currentDepartureIndex, currentAgentBoardingTime, currentBoardingRouteStopIndex, toRouteStopIndex); RRouteStop toRouteStop = this.data.routeStops[toRouteStopIndex]; + if (!toRouteStop.routeStop.isAllowAlighting()) { + continue; + } + this.routeSegmentIterator.reset(currentDepartureIndex, currentAgentBoardingTime, currentBoardingRouteStopIndex, toRouteStopIndex); int arrivalTime = currentDepartureTime + toRouteStop.arrivalOffset; int inVehicleTime = arrivalTime - currentAgentBoardingTime; double inVehicleCost = this.inVehicleCostCalculator.getInVehicleCost(inVehicleTime, marginalUtilityOfTravelTime_utl_s, person, currentVehicle, parameters, routeSegmentIterator); @@ -814,17 +826,17 @@ private void handleTransfers(boolean strict, RaptorParameters raptorParams, Cach continue; } RRouteStop fromRouteStop = fromPE.toRouteStop; // this is the route stop we arrive with least cost at stop - + // obtain on-demand transfers if applicable (will return null if transfers are calculated initially) RTransfer[] transfers = this.data.calculateTransfers(fromRouteStop); - + int firstTransferIndex = transfers == null ? fromRouteStop.indexFirstTransfer : 0; int lastTransferIndex = transfers == null ? firstTransferIndex + fromRouteStop.countTransfers : transfers.length; transfers = transfers == null ? this.data.transfers : transfers; - + for (int transferIndex = firstTransferIndex; transferIndex < lastTransferIndex; transferIndex++) { RTransfer transfer = transfers[transferIndex]; - + int toRouteStopIndex = transfer.toRouteStop; transferProvider.reset(transfer); int newArrivalTime = arrivalTime + transfer.transferTime; diff --git a/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorData.java b/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorData.java index 4813fafd95d..7ec137e6096 100644 --- a/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorData.java +++ b/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorData.java @@ -81,7 +81,7 @@ public class SwissRailRaptorData { final QuadTree stopsQT; final Map>> stopFilterAttribute2Value2StopsQT; final OccupancyData occupancyData; - + // data needed if cached transfer construction is activated final IdMap> staticTransferTimes; final RTransfer[][] transferCache; @@ -105,7 +105,7 @@ private SwissRailRaptorData(RaptorStaticConfig config, int countStops, this.stopsQT = stopsQT; this.stopFilterAttribute2Value2StopsQT = new HashMap<>(); this.occupancyData = occupancyData; - + // data needed if cached transfer construction is activated this.staticTransferTimes = staticTransferTimes; this.transferCache = new RTransfer[routeStops.length][]; @@ -216,7 +216,7 @@ public static SwissRailRaptorData create(TransitSchedule schedule, @Nullable Veh // if cached transfer calculation is active, don't generate any transfers here final Map allTransfers; - + if (staticConfig.getTransferCalculation().equals(RaptorTransferCalculation.Initial)) { allTransfers = calculateRouteStopTransfers(schedule, stopsQT, routeStopsPerStopFacility, routeStops, staticConfig); @@ -244,7 +244,7 @@ public static SwissRailRaptorData create(TransitSchedule schedule, @Nullable Veh indexTransfer += transferCount; } } - + // if cached transfer calculation is used, build a map for quick lookup of minimal transfer times IdMap> staticTransferTimes = null; if (staticConfig.getTransferCalculation().equals(RaptorTransferCalculation.Cached)) { @@ -258,7 +258,7 @@ public static SwissRailRaptorData create(TransitSchedule schedule, @Nullable Veh .put(schedule.getFacilities().get(iterator.getToStopId()), iterator.getSeconds()); } } - + SwissRailRaptorData data = new SwissRailRaptorData(staticConfig, countStopFacilities, routes, departures, departureVehicles, departureIds, routeStops, transfers, stopFacilityIndices, routeStopsPerStopFacility, stopsQT, occupancyData, staticTransferTimes); long endMillis = System.currentTimeMillis(); @@ -327,7 +327,9 @@ private static Map calculateRouteStopTransfers(TransitSche stopTransfers.clear(); for (int toRouteStopIndex : toRouteStopIndices) { RRouteStop toRouteStop = routeStops[toRouteStopIndex]; - if (isUsefulTransfer(fromRouteStop, toRouteStop, maxBeelineWalkConnectionDistance, config.getOptimization())) { + if (isUsefulTransfer(fromRouteStop, toRouteStop, maxBeelineWalkConnectionDistance, config.getOptimization()) + && isTransferAllowed(fromRouteStop, toRouteStop) + ) { RTransfer newTransfer = new RTransfer(fromRouteStopIndex, toRouteStopIndex, fixedTransferTime, beelineDistance * beelineDistanceFactor); stopTransfers.add(newTransfer); } @@ -388,6 +390,10 @@ private static boolean isUsefulTransfer(RRouteStop fromRouteStop, RRouteStop toR return true; } + private static boolean isTransferAllowed(RRouteStop fromRouteStop, RRouteStop toRouteStop) { + return fromRouteStop.routeStop.isAllowAlighting() && toRouteStop.routeStop.isAllowBoarding(); + } + private static boolean isFirstStopInRoute(RRouteStop routeStop) { TransitRouteStop firstRouteStop = routeStop.route.getStops().get(0); return routeStop.routeStop == firstRouteStop; @@ -641,12 +647,12 @@ public Transfer get() { return this.transfer; } } - + RTransfer[] calculateTransfers(RRouteStop fromRouteStop) { if (config.getTransferCalculation().equals(RaptorTransferCalculation.Initial)) { return null; } - + // We tested this in a parallel set-up and things seem to work as they are // implemented. The routing threads will access the cache as read-only an // retrieve the cached stop connections. It can happen that two of them try to @@ -661,41 +667,41 @@ RTransfer[] calculateTransfers(RRouteStop fromRouteStop) { RTransfer[] cache = transferCache[fromRouteStop.index]; if (cache != null) return cache; // we had a cache hit - + // setting up useful constants final double minimalTransferTime = config.getMinimalTransferTime(); final double beelineWalkConnectionDistance = config.getBeelineWalkConnectionDistance(); final double beelineDistanceFactor = config.getBeelineWalkDistanceFactor(); final double beelineWalkSpeed = config.getBeelineWalkSpeed(); final RaptorOptimization optimization = config.getOptimization(); - + // the facility from which we want to transfer TransitStopFacility fromRouteFacility = fromRouteStop.routeStop.getStopFacility(); Collection transferCandidates = new LinkedList<>(); - + // find transfer candidates by distance transferCandidates.addAll(stopsQT.getDisk(fromRouteFacility.getCoord().getX(), fromRouteFacility.getCoord().getY(), config.getBeelineWalkConnectionDistance())); - + // find transfer candidates with predefined transfer time Map transferTimes = staticTransferTimes.get(fromRouteFacility.getId()); - + if (transferTimes != null) { // some transfer times are predefined transferCandidates.addAll(transferTimes.keySet()); } - + // now evaluate whether transfers are useful, distance, and travel time List transfers = new LinkedList<>(); for (TransitStopFacility toRouteFacility : transferCandidates) { for (int toRouteStopIndex : routeStopsPerStopFacility.get(toRouteFacility)) { RRouteStop toRouteStop = routeStops[toRouteStopIndex]; - + double beelineDistance = CoordUtils.calcEuclideanDistance(fromRouteFacility.getCoord(), toRouteFacility.getCoord()); double transferTime = beelineDistance / beelineWalkSpeed; - + if (transferTime < minimalTransferTime) { transferTime = minimalTransferTime; } - + if (transferTimes != null) { // check if we find a predefined transfer time transferTime = transferTimes.getOrDefault(toRouteFacility, transferTime); @@ -706,10 +712,10 @@ RTransfer[] calculateTransfers(RRouteStop fromRouteStop) { } } } - + // convert to array RTransfer[] stopTransfers = transfers.toArray(new RTransfer[transfers.size()]); - + // save to cache (no issue regarding parallel execution because we simply set an element) transferCache[fromRouteStop.index] = stopTransfers; return stopTransfers; diff --git a/matsim/src/main/java/org/matsim/pt/transitSchedule/Constants.java b/matsim/src/main/java/org/matsim/pt/transitSchedule/Constants.java index 88a55b790f0..8045d019c53 100644 --- a/matsim/src/main/java/org/matsim/pt/transitSchedule/Constants.java +++ b/matsim/src/main/java/org/matsim/pt/transitSchedule/Constants.java @@ -51,6 +51,8 @@ abstract class Constants { static final String VEHICLE_REF_ID = "vehicleRefId"; static final String DEPARTURE_OFFSET = "departureOffset"; static final String ARRIVAL_OFFSET = "arrivalOffset"; + static final String ALLOW_BOARDING = "allowBoarding"; + static final String ALLOW_ALIGHTING = "allowAlighting"; static final String AWAIT_DEPARTURE = "awaitDeparture"; static final String IS_BLOCKING = "isBlocking"; static final String STOP_AREA_ID = "stopAreaId"; diff --git a/matsim/src/main/java/org/matsim/pt/transitSchedule/TransitRouteStopImpl.java b/matsim/src/main/java/org/matsim/pt/transitSchedule/TransitRouteStopImpl.java index e9123814f35..4193e872511 100644 --- a/matsim/src/main/java/org/matsim/pt/transitSchedule/TransitRouteStopImpl.java +++ b/matsim/src/main/java/org/matsim/pt/transitSchedule/TransitRouteStopImpl.java @@ -37,11 +37,15 @@ public class TransitRouteStopImpl implements TransitRouteStop { private final OptionalTime departureOffset; private final OptionalTime arrivalOffset; private boolean awaitDepartureTime = false; + private boolean allowBoarding = true; + private boolean allowAlighting = true; private TransitRouteStopImpl(Builder builder) { - stop = builder.stop; - departureOffset = builder.departureOffset; - arrivalOffset = builder.arrivalOffset; + this.stop = builder.stop; + this.departureOffset = builder.departureOffset; + this.arrivalOffset = builder.arrivalOffset; + this.allowBoarding = builder.allowBoarding; + this.allowAlighting = builder.allowAlighting; setAwaitDepartureTime(builder.awaitDepartureTime); } @@ -65,6 +69,26 @@ public OptionalTime getArrivalOffset() { return this.arrivalOffset; } + @Override + public boolean isAllowBoarding() { + return this.allowBoarding; + } + + @Override + public void setAllowBoarding(boolean allowBoarding) { + this.allowBoarding = allowBoarding; + } + + @Override + public boolean isAllowAlighting() { + return this.allowAlighting; + } + + @Override + public void setAllowAlighting(boolean allowAlighting) { + this.allowAlighting = allowAlighting; + } + @Override public boolean isAwaitDepartureTime() { return this.awaitDepartureTime; @@ -77,14 +101,13 @@ public void setAwaitDepartureTime(final boolean awaitDepartureTime) { /** * TransitRouteStops are typical Value Objects, so we consider two stops equal if they are equal field-wise. - * + * */ @Override public boolean equals(Object obj) { - if (!(obj instanceof TransitRouteStopImpl)) { + if (!(obj instanceof TransitRouteStopImpl other)) { return false; } - TransitRouteStopImpl other = (TransitRouteStopImpl) obj; if (this.stop == null) { if (other.getStopFacility() != null) { return false; @@ -96,10 +119,16 @@ public boolean equals(Object obj) { } if (!this.departureOffset.equals(other.getDepartureOffset())) { return false; - } + } if (!this.arrivalOffset.equals(other.getArrivalOffset())) { return false; } + if (this.allowBoarding != other.allowBoarding) { + return false; + } + if (this.allowAlighting != other.allowAlighting) { + return false; + } if (this.awaitDepartureTime != other.isAwaitDepartureTime()) { return false; } @@ -110,7 +139,7 @@ public boolean equals(Object obj) { public int hashCode() { return stop.hashCode(); } - + @Override public String toString() { return "[TransitRouteStop stop=" + this.stop.getId() + " offset=" + this.departureOffset +" ]"; @@ -120,6 +149,8 @@ public static final class Builder implements TransitRouteStop.Builder { private TransitStopFacility stop; private OptionalTime departureOffset = OptionalTime.undefined(); private OptionalTime arrivalOffset = OptionalTime.undefined(); + private boolean allowBoarding = true; + private boolean allowAlighting = true; private boolean awaitDepartureTime; public Builder() { @@ -157,6 +188,16 @@ public Builder arrivalOffset(OptionalTime val) { return this; } + public Builder allowBoarding(boolean allowBoarding) { + this.allowBoarding = allowBoarding; + return this; + } + + public Builder allowAlighting(boolean allowAlighting) { + this.allowAlighting = allowAlighting; + return this; + } + public Builder awaitDepartureTime(boolean val) { awaitDepartureTime = val; return this; diff --git a/matsim/src/main/java/org/matsim/pt/transitSchedule/TransitScheduleReaderV2.java b/matsim/src/main/java/org/matsim/pt/transitSchedule/TransitScheduleReaderV2.java index 4c364538f3b..2ef65e449d3 100644 --- a/matsim/src/main/java/org/matsim/pt/transitSchedule/TransitScheduleReaderV2.java +++ b/matsim/src/main/java/org/matsim/pt/transitSchedule/TransitScheduleReaderV2.java @@ -175,6 +175,8 @@ public void startTag(final String name, final Attributes atts, final Stack stops) throws Unchec .ifDefined(offset -> attributes.add(createTimeTuple(Constants.ARRIVAL_OFFSET, offset))); stop.getDepartureOffset().ifDefined(offset-> attributes.add(createTimeTuple(Constants.DEPARTURE_OFFSET, offset))); + // do not write out if it is true ==> the default value + if (!stop.isAllowBoarding()) { + attributes.add(createTuple(Constants.ALLOW_BOARDING, String.valueOf(stop.isAllowBoarding()))); + } + if (!stop.isAllowAlighting()) { + attributes.add(createTuple(Constants.ALLOW_ALIGHTING, String.valueOf(stop.isAllowAlighting()))); + } attributes.add(createTuple(Constants.AWAIT_DEPARTURE, String.valueOf(stop.isAwaitDepartureTime()))); this.writeStartTag(Constants.STOP, attributes, true); } diff --git a/matsim/src/main/java/org/matsim/pt/transitSchedule/api/TransitRouteStop.java b/matsim/src/main/java/org/matsim/pt/transitSchedule/api/TransitRouteStop.java index 108e52cb6db..dcc0e51d9cd 100644 --- a/matsim/src/main/java/org/matsim/pt/transitSchedule/api/TransitRouteStop.java +++ b/matsim/src/main/java/org/matsim/pt/transitSchedule/api/TransitRouteStop.java @@ -38,6 +38,16 @@ public interface TransitRouteStop { public abstract OptionalTime getArrivalOffset(); + /** @return true if agents are allowed to board the transit vehicle at this route stop. */ + boolean isAllowBoarding(); + + void setAllowBoarding(boolean allowBoarding); + + /** @return true if agents are allowed to exit the transit vehicle at this route stop. */ + boolean isAllowAlighting(); + + void setAllowAlighting(boolean allowAlighting); + /** * Specifies if a driver should wait until the specified departure time * has come before departing, especially if the driver is too early at @@ -69,6 +79,10 @@ interface Builder> { Builder awaitDepartureTime(boolean val); + Builder allowBoarding(boolean val); + + Builder allowAlighting(boolean val); + TransitRouteStop build(); } -} \ No newline at end of file +} diff --git a/matsim/src/main/resources/dtd/transitSchedule_v2.dtd b/matsim/src/main/resources/dtd/transitSchedule_v2.dtd index cf3665e0679..5c030f2279c 100644 --- a/matsim/src/main/resources/dtd/transitSchedule_v2.dtd +++ b/matsim/src/main/resources/dtd/transitSchedule_v2.dtd @@ -54,6 +54,8 @@ refId CDATA #REQUIRED departureOffset CDATA #IMPLIED arrivalOffset CDATA #IMPLIED + allowBoarding (true|false) "true" + allowAlighting (true|false) "true" awaitDeparture (true|false) "false">