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 02ae5072583..e39eedd9ad4 100644 --- a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/DemandReaderFromCSV.java +++ b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/DemandReaderFromCSV.java @@ -550,6 +550,7 @@ static void createDemandForCarriers(Scenario scenario, ShpOptions.Index indexSha CoordinateTransformation crsTransformationNetworkAndShape) { for (DemandInformationElement newDemandInformationElement : demandInformation) { + log.info("Create demand for carrier {}", newDemandInformationElement.getCarrierName()); if (newDemandInformationElement.getTypeOfDemand().equals("service")) createServices(scenario, newDemandInformationElement, indexShape, population, combineSimilarJobs, crsTransformationNetworkAndShape); @@ -585,12 +586,16 @@ private static void createServices(Scenario scenario, DemandInformationElement n Integer numberOfServiceLocations = newDemandInformationElement.getNumberOfFirstJobElementLocations(); ArrayList usedServiceLocations = new ArrayList(); int numberOfLinksInNetwork = scenario.getNetwork().getLinks().size(); - HashMap, Person> possiblePersonsForService = new HashMap, Person>(); + HashMap, Person> possiblePersonsForService = new HashMap<>(); HashMap, HashMap> nearestLinkPerPerson = new HashMap<>(); // set number of jobs - if (shareOfPopulationWithThisService == null) + if (shareOfPopulationWithThisService == null) { numberOfJobs = newDemandInformationElement.getNumberOfJobs(); + if (population != null) + log.warn( + "You have a population but no share of the population for the demand. The number of jobs will be set to the number of jobs you set in the csv file. The population will not be used for the demand generation."); + } else if (population == null) throw new RuntimeException( "No population found although input parameter is set"); @@ -606,15 +611,14 @@ else if (population == null) possiblePersonsForService.putAll(population.getPersons()); int numberPossibleServices = (int) Math .round(shareOfPopulationWithThisService * possiblePersonsForService.size()); - if (sampleSizeInputPopulation == sampleTo) - numberOfJobs = (int) Math.round(shareOfPopulationWithThisService * possiblePersonsForService.size()); - else if (samplingOption.equals("changeNumberOfLocationsWithDemand")) - numberOfJobs = (int) Math.round((sampleTo / sampleSizeInputPopulation) - * (shareOfPopulationWithThisService * possiblePersonsForService.size())); - else if (samplingOption.equals("changeDemandOnLocation")) { - demandToDistribute = (int) Math.round((sampleTo / sampleSizeInputPopulation) * demandToDistribute); - numberOfJobs = (int) Math.round(shareOfPopulationWithThisService * possiblePersonsForService.size()); - } else + int sampledNumberPossibleServices = (int) Math.round((sampleTo / sampleSizeInputPopulation) * numberPossibleServices); + if (sampleSizeInputPopulation == sampleTo || samplingOption.equals("changeDemandOnLocation")) + numberOfJobs = numberPossibleServices; + else if (samplingOption.equals("changeNumberOfLocationsWithDemand")) { + numberOfJobs = sampledNumberPossibleServices; + numberPossibleServices = numberOfJobs; + } + else throw new RuntimeException( "Error with the sampling of the demand based on the population. Please check sampling sizes and sampling options!!"); if (numberPossibleServices != 0) @@ -773,16 +777,20 @@ private static void createShipments(Scenario scenario, DemandInformationElement String[] areasForDeliveryLocations = newDemandInformationElement.getAreasSecondJobElement(); String[] setLocationsOfPickup = newDemandInformationElement.getLocationsOfFirstJobElement(); String[] setLocationsOfDelivery = newDemandInformationElement.getLocationsOfSecondJobElement(); - ArrayList usedPickupLocations = new ArrayList(); - ArrayList usedDeliveryLocations = new ArrayList(); - HashMap, Person> possiblePersonsPickup = new HashMap, Person>(); - HashMap, Person> possiblePersonsDelivery = new HashMap, Person>(); + ArrayList usedPickupLocations = new ArrayList<>(); + ArrayList usedDeliveryLocations = new ArrayList<>(); + HashMap, Person> possiblePersonsPickup = new HashMap<>(); + HashMap, Person> possiblePersonsDelivery = new HashMap<>(); HashMap, HashMap> nearestLinkPerPersonPickup = new HashMap<>(); HashMap, HashMap> nearestLinkPerPersonDelivery = new HashMap<>(); // set number of jobs - if (shareOfPopulationWithThisPickup == null && shareOfPopulationWithThisDelivery == null) + if (shareOfPopulationWithThisPickup == null && shareOfPopulationWithThisDelivery == null){ + if (population != null) + log.warn( + "You have a population but no share of the population for the demand. The number of jobs will be set to the number of jobs you set in the csv file. The population will not be used for the demand generation."); numberOfJobs = newDemandInformationElement.getNumberOfJobs(); + } else if (population == null) throw new RuntimeException( "No population found although input parameter is set"); @@ -814,37 +822,24 @@ else if (population == null) 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); - numberPossibleJobsPickup = numberOfJobs; - if (shareOfPopulationWithThisDelivery != null) - numberPossibleJobsDelivery = (int) Math - .round(shareOfPopulationWithThisDelivery * numberPossibleJobsDelivery); + if (sampleSizeInputPopulation == sampleTo ||samplingOption.equals("changeDemandOnLocation")) { + numberOfJobs = numberPossibleJobsPickup; } else if (samplingOption.equals("changeNumberOfLocationsWithDemand")) { numberOfJobs = sampledNumberPossibleJobsPickup; numberPossibleJobsPickup = numberOfJobs; if (shareOfPopulationWithThisDelivery != null) numberPossibleJobsDelivery = sampledNumberPossibleJobsDelivery; - } else if (samplingOption.equals("changeDemandOnLocation")) { - demandToDistribute = (int) Math.round((sampleTo / sampleSizeInputPopulation) * demandToDistribute); - numberOfJobs = numberPossibleJobsPickup; } else throw new RuntimeException( "Error with the sampling of the demand based on the population. Please check sampling sizes and sampling options!!"); } else { - if (sampleSizeInputPopulation == sampleTo) { - numberOfJobs = (int) Math.round(shareOfPopulationWithThisDelivery * numberPossibleJobsDelivery); - numberPossibleJobsDelivery = numberOfJobs; - numberPossibleJobsPickup = (int) Math - .round(shareOfPopulationWithThisPickup * numberPossibleJobsPickup); + if (sampleSizeInputPopulation == sampleTo ||samplingOption.equals("changeDemandOnLocation")) { + numberOfJobs = numberPossibleJobsDelivery; } else if (samplingOption.equals("changeNumberOfLocationsWithDemand")) { numberOfJobs = sampledNumberPossibleJobsDelivery; numberPossibleJobsDelivery = numberOfJobs; if (shareOfPopulationWithThisDelivery != null) numberPossibleJobsPickup = sampledNumberPossibleJobsPickup; - } else if (samplingOption.equals("changeDemandOnLocation")) { - demandToDistribute = (int) Math.round((sampleTo / sampleSizeInputPopulation) * demandToDistribute); - numberOfJobs = numberPossibleJobsDelivery; } else throw new RuntimeException( "Error with the sampling of the demand based on the population. Please check sampling sizes and sampling options!!"); @@ -1289,6 +1284,7 @@ private static HashMap, Link> findAllPossibleLinks(Scenario scenario, Integer numberOfLocations, String[] areasForLocations, String[] setLocations, HashMap, Person> possiblePersons, HashMap, HashMap> nearestLinkPerPerson) { + log.info("Finding possible links for the demand in the selected areas {}", Arrays.toString(areasForLocations)); HashMap, Link> possibleLinks = new HashMap<>(); if (numberOfLocations == null) { for (Link link : scenario.getNetwork().getLinks().values()) @@ -1364,7 +1360,7 @@ private static Link findNextUsedLink(Scenario scenario, ShpOptions.Index indexSh private static HashMap, Person> findPossiblePersons(Population population, String[] areasForJobElementLocations, ShpOptions.Index indexShape, CoordinateTransformation crsTransformationNetworkAndShape) { - + log.info("Finding possible persons for the demand in the selected areas {}", Arrays.toString(areasForJobElementLocations)); HashMap, Person> possiblePersons = new HashMap<>(); for (Person person : population.getPersons().values()) { 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 09ba9e75623..368dddaad69 100644 --- a/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGeneration.java +++ b/contribs/application/src/main/java/org/matsim/freightDemandGeneration/FreightDemandGeneration.java @@ -374,13 +374,16 @@ private void createDemand(DemandGenerationOptions selectedDemandGenerationOption */ FreightDemandGenerationUtils.preparePopulation(population, sampleSizeInputPopulation, upSamplePopulationTo, "changeNumberOfLocationsWithDemand"); - case increaseDemandOnLocation -> + case increaseDemandOnLocation -> { /* * If the demand sample is higher than the population sample, the demand per * person will be increased. */ - FreightDemandGenerationUtils.preparePopulation(population, sampleSizeInputPopulation, - upSamplePopulationTo, "changeDemandOnLocation"); + log.warn("You have selected the option to increase the demand on the location. " + + "Because the simulation always uses the given demand the results are similar to the option with the same sample size."); + FreightDemandGenerationUtils.preparePopulation(population, sampleSizeInputPopulation, + upSamplePopulationTo, "changeDemandOnLocation"); + } case noPopulationSampling -> /* * If the demand sample is equal to the population sample, the demand is created diff --git a/contribs/application/src/test/java/org/matsim/freightDemandGeneration/DemandReaderFromCSVTest.java b/contribs/application/src/test/java/org/matsim/freightDemandGeneration/DemandReaderFromCSVTest.java index 9d672b4a461..c27b251afc4 100644 --- a/contribs/application/src/test/java/org/matsim/freightDemandGeneration/DemandReaderFromCSVTest.java +++ b/contribs/application/src/test/java/org/matsim/freightDemandGeneration/DemandReaderFromCSVTest.java @@ -2,13 +2,11 @@ import java.io.IOException; import java.nio.file.Path; -import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; -import org.geotools.api.feature.simple.SimpleFeature; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -22,7 +20,6 @@ import org.matsim.freight.carriers.*; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; -import org.matsim.core.network.NetworkUtils; import org.matsim.core.population.PopulationUtils; import org.matsim.core.scenario.ScenarioUtils; import org.matsim.freightDemandGeneration.CarrierReaderFromCSV.CarrierInformationElement; @@ -41,7 +38,7 @@ public class DemandReaderFromCSVTest { private MatsimTestUtils utils = new MatsimTestUtils(); @Test - void testLinkForPerson() throws IOException { + void testLinkForPerson() { Config config = ConfigUtils.createConfig(); config.network().setInputFile( "https://raw.githubusercontent.com/matsim-org/matsim-libs/master/examples/scenarios/freight-chessboard-9x9/grid9x9.xml"); @@ -61,13 +58,10 @@ void testLinkForPerson() throws IOException { Assertions.assertEquals("j(8,8)R",nearestLinkPerPerson.get(Id.createPersonId("person6")).values().iterator().next()); Assertions.assertEquals("i(5,9)R",nearestLinkPerPerson.get(Id.createPersonId("person7")).values().iterator().next()); Assertions.assertEquals("i(9,5)R",nearestLinkPerPerson.get(Id.createPersonId("person8")).values().iterator().next()); - - - } @Test - void demandCreation() throws IOException { + void demandCreationWithSampleWithChangeNumberOfLocations() throws IOException { // read inputs Config config = ConfigUtils.createConfig(); config.network().setInputFile( @@ -82,126 +76,21 @@ void demandCreation() throws IOException { ShpOptions shp = new ShpOptions(shapeFilePath, "WGS84", null); String shapeCategory = "Ortsteil"; ShpOptions.Index indexShape = shp.createIndex("Ortsteil"); - Collection polygonsInShape = shp.readFeatures(); String populationLocation = utils.getPackageInputDirectory() + "testPopulation.xml"; Population population = PopulationUtils.readPopulation(populationLocation); FreightDemandGenerationUtils.preparePopulation(population, 0.5, 1.0, "changeNumberOfLocationsWithDemand"); // run methods - Set allNewCarrierInformation = CarrierReaderFromCSV - .readCarrierInformation(carrierCSVLocation); - CarrierReaderFromCSV.createNewCarrierAndAddVehicleTypes(scenario, allNewCarrierInformation, freightCarriersConfigGroup, - indexShape, 1, null); - Set demandInformation = DemandReaderFromCSV.readDemandInformation(demandCSVLocation); - DemandReaderFromCSV.checkNewDemand(scenario, demandInformation, indexShape, shapeCategory); - DemandReaderFromCSV.createDemandForCarriers(scenario, indexShape, demandInformation, population, false, - null); - Assertions.assertEquals(3, CarriersUtils.getCarriers(scenario).getCarriers().size()); - Assertions.assertTrue( - CarriersUtils.getCarriers(scenario).getCarriers().containsKey(Id.create("testCarrier1", Carrier.class))); - Assertions.assertTrue( - CarriersUtils.getCarriers(scenario).getCarriers().containsKey(Id.create("testCarrier2", Carrier.class))); - Assertions.assertTrue( - CarriersUtils.getCarriers(scenario).getCarriers().containsKey(Id.create("testCarrier3", Carrier.class))); + createDemandAndCheckCarrier(carrierCSVLocation, scenario, freightCarriersConfigGroup, indexShape, demandCSVLocation, shapeCategory, + population); - // check carrier 1 - Network network = NetworkUtils.readNetwork( - "https://raw.githubusercontent.com/matsim-org/matsim-libs/master/examples/scenarios/freight-chessboard-9x9/grid9x9.xml"); - Carrier testCarrier1 = CarriersUtils.getCarriers(scenario).getCarriers() - .get(Id.create("testCarrier1", Carrier.class)); - Assertions.assertEquals(14, testCarrier1.getServices().size()); - Assertions.assertEquals(0, testCarrier1.getShipments().size()); - Object2IntMap countServicesWithCertainDemand = new Object2IntOpenHashMap<>(); - Map> locationsPerServiceElement = new HashMap<>(); - int countDemand = 0; - for (CarrierService service : testCarrier1.getServices().values()) { - countServicesWithCertainDemand.merge((Integer) service.getCapacityDemand(), 1, Integer::sum); - countDemand = countDemand + service.getCapacityDemand(); - if (service.getCapacityDemand() == 0) { - Assertions.assertEquals(180, service.getServiceDuration(), MatsimTestUtils.EPSILON); - Assertions.assertEquals(TimeWindow.newInstance(3000, 13000), service.getServiceStartTimeWindow()); - locationsPerServiceElement.computeIfAbsent("serviceElement1", (k) -> new HashSet<>()) - .add(service.getLocationLinkId().toString()); - } else if (service.getCapacityDemand() == 1) { - Assertions.assertEquals(100, service.getServiceDuration(), MatsimTestUtils.EPSILON); - Assertions.assertEquals(TimeWindow.newInstance(5000, 20000), service.getServiceStartTimeWindow()); - locationsPerServiceElement.computeIfAbsent("serviceElement2", (k) -> new HashSet<>()) - .add(service.getLocationLinkId().toString()); - } else if (service.getCapacityDemand() == 2) { - Assertions.assertEquals(200, service.getServiceDuration(), MatsimTestUtils.EPSILON); - Assertions.assertEquals(TimeWindow.newInstance(5000, 20000), service.getServiceStartTimeWindow()); - locationsPerServiceElement.computeIfAbsent("serviceElement2", (k) -> new HashSet<>()) - .add(service.getLocationLinkId().toString()); - } else - Assertions.fail("Service has a wrong demand."); - } - Assertions.assertEquals(12, countDemand); - Assertions.assertEquals(4, countServicesWithCertainDemand.getInt(0)); - Assertions.assertEquals(8, countServicesWithCertainDemand.getInt(1)); - Assertions.assertEquals(2, countServicesWithCertainDemand.getInt(2)); - Assertions.assertEquals(4, locationsPerServiceElement.get("serviceElement1").size()); - for (String locationsOfServiceElement : locationsPerServiceElement.get("serviceElement1")) { - Link link = network.getLinks().get(Id.createLinkId(locationsOfServiceElement)); - Assertions.assertTrue( - FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, null, null)); - Assertions.assertFalse(FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, - new String[] { "area1" }, null)); - Assertions.assertTrue(FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, - new String[] { "area2" }, null)); - } - Assertions.assertEquals(4, locationsPerServiceElement.get("serviceElement2").size()); - Assertions.assertTrue(locationsPerServiceElement.get("serviceElement2").contains("i(2,0)")); + Network network = scenario.getNetwork(); - // check carrier 2 - Carrier testCarrier2 = CarriersUtils.getCarriers(scenario).getCarriers() - .get(Id.create("testCarrier2", Carrier.class)); - Assertions.assertEquals(0, testCarrier2.getServices().size()); - Assertions.assertEquals(11, testCarrier2.getShipments().size()); - Object2IntMap countShipmentsWithCertainDemand = new Object2IntOpenHashMap<>(); - Map> locationsPerShipmentElement = new HashMap<>(); - countDemand = 0; - for (CarrierShipment shipment : testCarrier2.getShipments().values()) { - countShipmentsWithCertainDemand.merge((Integer) shipment.getSize(), 1, Integer::sum); - countDemand = countDemand + shipment.getSize(); - if (shipment.getSize() == 0) { - Assertions.assertEquals(300, shipment.getPickupServiceTime(), MatsimTestUtils.EPSILON); - Assertions.assertEquals(350, shipment.getDeliveryServiceTime(), MatsimTestUtils.EPSILON); - Assertions.assertEquals(TimeWindow.newInstance(10000, 45000), shipment.getPickupTimeWindow()); - Assertions.assertEquals(TimeWindow.newInstance(11000, 44000), shipment.getDeliveryTimeWindow()); - locationsPerShipmentElement.computeIfAbsent("ShipmenElement1_pickup", (k) -> new HashSet<>()) - .add(shipment.getFrom().toString()); - locationsPerShipmentElement.computeIfAbsent("ShipmenElement1_delivery", (k) -> new HashSet<>()) - .add(shipment.getTo().toString()); - } else if (shipment.getSize() == 2) { - Assertions.assertEquals(400, shipment.getPickupServiceTime(), MatsimTestUtils.EPSILON); - Assertions.assertEquals(400, shipment.getDeliveryServiceTime(), MatsimTestUtils.EPSILON); - Assertions.assertEquals(TimeWindow.newInstance(11000, 44000), shipment.getPickupTimeWindow()); - Assertions.assertEquals(TimeWindow.newInstance(20000, 40000), shipment.getDeliveryTimeWindow()); - locationsPerShipmentElement.computeIfAbsent("ShipmenElement2_pickup", (k) -> new HashSet<>()) - .add(shipment.getFrom().toString()); - locationsPerShipmentElement.computeIfAbsent("ShipmenElement2_delivery", (k) -> new HashSet<>()) - .add(shipment.getTo().toString()); - } else if (shipment.getSize() == 3) { - Assertions.assertEquals(600, shipment.getPickupServiceTime(), MatsimTestUtils.EPSILON); - Assertions.assertEquals(600, shipment.getDeliveryServiceTime(), MatsimTestUtils.EPSILON); - Assertions.assertEquals(TimeWindow.newInstance(11000, 44000), shipment.getPickupTimeWindow()); - Assertions.assertEquals(TimeWindow.newInstance(20000, 40000), shipment.getDeliveryTimeWindow()); - locationsPerShipmentElement.computeIfAbsent("ShipmenElement2_pickup", (k) -> new HashSet<>()) - .add(shipment.getFrom().toString()); - locationsPerShipmentElement.computeIfAbsent("ShipmenElement2_delivery", (k) -> new HashSet<>()) - .add(shipment.getTo().toString()); - } else - Assertions.fail("Shipment has an unexpected demand."); - } - Assertions.assertEquals(15, countDemand); - Assertions.assertEquals(4, countShipmentsWithCertainDemand.getInt(0)); - Assertions.assertEquals(6, countShipmentsWithCertainDemand.getInt(2)); - Assertions.assertEquals(1, countShipmentsWithCertainDemand.getInt(3)); - Assertions.assertEquals(4, locationsPerShipmentElement.get("ShipmenElement1_pickup").size()); - Assertions.assertEquals(1, locationsPerShipmentElement.get("ShipmenElement1_delivery").size()); - Assertions.assertTrue(locationsPerShipmentElement.get("ShipmenElement1_delivery").contains("i(2,0)")); - Assertions.assertEquals(1, locationsPerShipmentElement.get("ShipmenElement2_pickup").size()); - Assertions.assertEquals(2, locationsPerShipmentElement.get("ShipmenElement2_delivery").size()); + checkCarrier1and2(scenario, network, indexShape); + + Object2IntMap countShipmentsWithCertainDemand; + Map> locationsPerShipmentElement; + int countDemand; // check carrier 3 Carrier testCarrier3 = CarriersUtils.getCarriers(scenario).getCarriers() @@ -219,16 +108,16 @@ void demandCreation() throws IOException { Assertions.assertEquals(1250, shipment.getDeliveryServiceTime(), MatsimTestUtils.EPSILON); Assertions.assertEquals(TimeWindow.newInstance(8000, 50000), shipment.getPickupTimeWindow()); Assertions.assertEquals(TimeWindow.newInstance(10000, 60000), shipment.getDeliveryTimeWindow()); - locationsPerShipmentElement.computeIfAbsent("ShipmenElement1_pickup", (k) -> new HashSet<>()) + locationsPerShipmentElement.computeIfAbsent("ShipmentElement1_pickup", (k) -> new HashSet<>()) .add(shipment.getFrom().toString()); - locationsPerShipmentElement.computeIfAbsent("ShipmenElement1_delivery", (k) -> new HashSet<>()) + locationsPerShipmentElement.computeIfAbsent("ShipmentElement1_delivery", (k) -> new HashSet<>()) .add(shipment.getTo().toString()); } Assertions.assertEquals(20, countDemand); Assertions.assertEquals(4, countShipmentsWithCertainDemand.getInt(5)); - Assertions.assertEquals(2, locationsPerShipmentElement.get("ShipmenElement1_pickup").size()); - Assertions.assertEquals(4, locationsPerShipmentElement.get("ShipmenElement1_delivery").size()); - for (String locationsOfShipmentElement : locationsPerShipmentElement.get("ShipmenElement1_delivery")) { + Assertions.assertEquals(2, locationsPerShipmentElement.get("ShipmentElement1_pickup").size()); + Assertions.assertEquals(4, locationsPerShipmentElement.get("ShipmentElement1_delivery").size()); + for (String locationsOfShipmentElement : locationsPerShipmentElement.get("ShipmentElement1_delivery")) { Link link = network.getLinks().get(Id.createLinkId(locationsOfShipmentElement)); Assertions.assertTrue( FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, null, null)); @@ -239,6 +128,140 @@ void demandCreation() throws IOException { } } + @Test + void demandCreationWithSampleWithDemandOnLocation() throws IOException { + // read inputs + Config config = ConfigUtils.createConfig(); + config.network().setInputFile( + "https://raw.githubusercontent.com/matsim-org/matsim-libs/master/examples/scenarios/freight-chessboard-9x9/grid9x9.xml"); + Scenario scenario = ScenarioUtils.loadScenario(config); + FreightCarriersConfigGroup freightCarriersConfigGroup = ConfigUtils.addOrGetModule(scenario.getConfig(), + FreightCarriersConfigGroup.class); + freightCarriersConfigGroup.setCarriersVehicleTypesFile(utils.getPackageInputDirectory() + "testVehicleTypes.xml"); + Path carrierCSVLocation = Path.of(utils.getPackageInputDirectory() + "testCarrierCSV.csv"); + Path demandCSVLocation = Path.of(utils.getPackageInputDirectory() + "testDemandCSV.csv"); + Path shapeFilePath = Path.of(utils.getPackageInputDirectory() + "testShape/testShape.shp"); + ShpOptions shp = new ShpOptions(shapeFilePath, "WGS84", null); + String shapeCategory = "Ortsteil"; + ShpOptions.Index indexShape = shp.createIndex("Ortsteil"); + String populationLocation = utils.getPackageInputDirectory() + "testPopulation.xml"; + Population population = PopulationUtils.readPopulation(populationLocation); + FreightDemandGenerationUtils.preparePopulation(population, 0.5, 1.0, "changeDemandOnLocation"); + + createDemandAndCheckCarrier(carrierCSVLocation, scenario, freightCarriersConfigGroup, indexShape, demandCSVLocation, shapeCategory, population); + + // check carrier 1 + Network network = scenario.getNetwork(); + + checkCarrier1and2(scenario, network, indexShape); + int countDemand; + Object2IntMap countShipmentsWithCertainDemand; + Map> locationsPerShipmentElement; + + // check carrier 3 + Carrier testCarrier3 = CarriersUtils.getCarriers(scenario).getCarriers() + .get(Id.create("testCarrier3", Carrier.class)); + Assertions.assertEquals(0, testCarrier3.getServices().size()); + Assertions.assertEquals(2, testCarrier3.getShipments().size()); + countShipmentsWithCertainDemand = new Object2IntOpenHashMap<>(); + locationsPerShipmentElement = new HashMap<>(); + countDemand = 0; + for (CarrierShipment shipment : testCarrier3.getShipments().values()) { + countShipmentsWithCertainDemand.merge((Integer) shipment.getSize(), 1, Integer::sum); + countDemand = countDemand + shipment.getSize(); + Assertions.assertEquals(10, shipment.getSize()); + Assertions.assertEquals(4000, shipment.getPickupServiceTime(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(2500, shipment.getDeliveryServiceTime(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(TimeWindow.newInstance(8000, 50000), shipment.getPickupTimeWindow()); + Assertions.assertEquals(TimeWindow.newInstance(10000, 60000), shipment.getDeliveryTimeWindow()); + locationsPerShipmentElement.computeIfAbsent("ShipmentElement1_pickup", (k) -> new HashSet<>()) + .add(shipment.getFrom().toString()); + locationsPerShipmentElement.computeIfAbsent("ShipmentElement1_delivery", (k) -> new HashSet<>()) + .add(shipment.getTo().toString()); + } + Assertions.assertEquals(20, countDemand); + Assertions.assertEquals(2, countShipmentsWithCertainDemand.getInt(10)); + Assertions.assertEquals(1, locationsPerShipmentElement.get("ShipmentElement1_pickup").size()); + Assertions.assertEquals(2, locationsPerShipmentElement.get("ShipmentElement1_delivery").size()); + for (String locationsOfShipmentElement : locationsPerShipmentElement.get("ShipmentElement1_delivery")) { + Link link = network.getLinks().get(Id.createLinkId(locationsOfShipmentElement)); + Assertions.assertTrue( + FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, null, null)); + Assertions.assertTrue(FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, + new String[] { "area1" }, null)); + Assertions.assertFalse(FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, + new String[] { "area2" }, null)); + } + } + + @Test + void demandCreationNoSampling() throws IOException { + // read inputs + Config config = ConfigUtils.createConfig(); + config.network().setInputFile( + "https://raw.githubusercontent.com/matsim-org/matsim-libs/master/examples/scenarios/freight-chessboard-9x9/grid9x9.xml"); + Scenario scenario = ScenarioUtils.loadScenario(config); + FreightCarriersConfigGroup freightCarriersConfigGroup = ConfigUtils.addOrGetModule(scenario.getConfig(), + FreightCarriersConfigGroup.class); + freightCarriersConfigGroup.setCarriersVehicleTypesFile(utils.getPackageInputDirectory() + "testVehicleTypes.xml"); + Path carrierCSVLocation = Path.of(utils.getPackageInputDirectory() + "testCarrierCSV.csv"); + Path demandCSVLocation = Path.of(utils.getPackageInputDirectory() + "testDemandCSV.csv"); + Path shapeFilePath = Path.of(utils.getPackageInputDirectory() + "testShape/testShape.shp"); + ShpOptions shp = new ShpOptions(shapeFilePath, "WGS84", null); + String shapeCategory = "Ortsteil"; + ShpOptions.Index indexShape = shp.createIndex("Ortsteil"); + String populationLocation = utils.getPackageInputDirectory() + "testPopulation.xml"; + Population population = PopulationUtils.readPopulation(populationLocation); + FreightDemandGenerationUtils.preparePopulation(population, 0.5, 0.5, "changeDemandOnLocation"); + + // run methods + createDemandAndCheckCarrier(carrierCSVLocation, scenario, freightCarriersConfigGroup, indexShape, demandCSVLocation, shapeCategory, + population); + + // check carrier 1 + Network network = scenario.getNetwork(); + + checkCarrier1and2(scenario, network, indexShape); + Object2IntMap countShipmentsWithCertainDemand; + Map> locationsPerShipmentElement; + int countDemand; + + // check carrier 3 + Carrier testCarrier3 = CarriersUtils.getCarriers(scenario).getCarriers() + .get(Id.create("testCarrier3", Carrier.class)); + Assertions.assertEquals(0, testCarrier3.getServices().size()); + Assertions.assertEquals(2, testCarrier3.getShipments().size()); + countShipmentsWithCertainDemand = new Object2IntOpenHashMap<>(); + locationsPerShipmentElement = new HashMap<>(); + countDemand = 0; + for (CarrierShipment shipment : testCarrier3.getShipments().values()) { + countShipmentsWithCertainDemand.merge((Integer) shipment.getSize(), 1, Integer::sum); + countDemand = countDemand + shipment.getSize(); + Assertions.assertEquals(10, shipment.getSize()); + Assertions.assertEquals(4000, shipment.getPickupServiceTime(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(2500, shipment.getDeliveryServiceTime(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(TimeWindow.newInstance(8000, 50000), shipment.getPickupTimeWindow()); + Assertions.assertEquals(TimeWindow.newInstance(10000, 60000), shipment.getDeliveryTimeWindow()); + locationsPerShipmentElement.computeIfAbsent("ShipmentElement1_pickup", (k) -> new HashSet<>()) + .add(shipment.getFrom().toString()); + locationsPerShipmentElement.computeIfAbsent("ShipmentElement1_delivery", (k) -> new HashSet<>()) + .add(shipment.getTo().toString()); + } + Assertions.assertEquals(20, countDemand); + Assertions.assertEquals(2, countShipmentsWithCertainDemand.getInt(10)); + Assertions.assertEquals(1, locationsPerShipmentElement.get("ShipmentElement1_pickup").size()); + Assertions.assertEquals(2, locationsPerShipmentElement.get("ShipmentElement1_delivery").size()); + for (String locationsOfShipmentElement : locationsPerShipmentElement.get("ShipmentElement1_delivery")) { + Link link = network.getLinks().get(Id.createLinkId(locationsOfShipmentElement)); + Assertions.assertTrue( + FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, null, null)); + Assertions.assertTrue(FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, + new String[] { "area1" }, null)); + Assertions.assertFalse(FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, + new String[] { "area2" }, null)); + } + } + @Test void csvDemandReader() throws IOException { @@ -295,7 +318,7 @@ void csvDemandReader() throws IOException { Assertions.assertNull(demandInformationElement.getAreasSecondJobElement()); Assertions.assertEquals(1, (int) demandInformationElement.getNumberOfSecondJobElementLocations()); Assertions.assertEquals(1, demandInformationElement.getLocationsOfSecondJobElement().length); - Assertions.assertTrue(demandInformationElement.getLocationsOfSecondJobElement()[0].equals("i(2,0)")); + Assertions.assertEquals("i(2,0)", demandInformationElement.getLocationsOfSecondJobElement()[0]); Assertions.assertEquals(350, (int) demandInformationElement.getSecondJobElementTimePerUnit()); Assertions.assertEquals(TimeWindow.newInstance(11000, 44000), demandInformationElement.getSecondJobElementTimeWindow()); @@ -341,4 +364,131 @@ void csvDemandReader() throws IOException { Assertions.fail("No expected demandInformationElement found"); } } + + private static void createDemandAndCheckCarrier(Path carrierCSVLocation, Scenario scenario, FreightCarriersConfigGroup freightCarriersConfigGroup, + ShpOptions.Index indexShape, Path demandCSVLocation, String shapeCategory, + Population population) throws IOException { + // run methods + Set allNewCarrierInformation = CarrierReaderFromCSV + .readCarrierInformation(carrierCSVLocation); + CarrierReaderFromCSV.createNewCarrierAndAddVehicleTypes(scenario, allNewCarrierInformation, freightCarriersConfigGroup, + indexShape, 1, null); + Set demandInformation = DemandReaderFromCSV.readDemandInformation(demandCSVLocation); + DemandReaderFromCSV.checkNewDemand(scenario, demandInformation, indexShape, shapeCategory); + DemandReaderFromCSV.createDemandForCarriers(scenario, indexShape, demandInformation, population, false, + null); + Assertions.assertEquals(3, CarriersUtils.getCarriers(scenario).getCarriers().size()); + Assertions.assertTrue( + CarriersUtils.getCarriers(scenario).getCarriers().containsKey(Id.create("testCarrier1", Carrier.class))); + Assertions.assertTrue( + CarriersUtils.getCarriers(scenario).getCarriers().containsKey(Id.create("testCarrier2", Carrier.class))); + Assertions.assertTrue( + CarriersUtils.getCarriers(scenario).getCarriers().containsKey(Id.create("testCarrier3", Carrier.class))); + } + + /** + * These results should be the same for these carriers. + * The difference is only based on the population sample methods for carrier3, because a shareOfThePopulation is used. + * + * @param scenario the scenario + * @param network the network + * @param indexShape the index of the shape + */ + private static void checkCarrier1and2(Scenario scenario, Network network, ShpOptions.Index indexShape) { + Carrier testCarrier1 = CarriersUtils.getCarriers(scenario).getCarriers() + .get(Id.create("testCarrier1", Carrier.class)); + Assertions.assertEquals(14, testCarrier1.getServices().size()); + Assertions.assertEquals(0, testCarrier1.getShipments().size()); + Object2IntMap countServicesWithCertainDemand = new Object2IntOpenHashMap<>(); + Map> locationsPerServiceElement = new HashMap<>(); + int countDemand = 0; + for (CarrierService service : testCarrier1.getServices().values()) { + countServicesWithCertainDemand.merge((Integer) service.getCapacityDemand(), 1, Integer::sum); + countDemand = countDemand + service.getCapacityDemand(); + if (service.getCapacityDemand() == 0) { + Assertions.assertEquals(180, service.getServiceDuration(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(TimeWindow.newInstance(3000, 13000), service.getServiceStartTimeWindow()); + locationsPerServiceElement.computeIfAbsent("serviceElement1", (k) -> new HashSet<>()) + .add(service.getLocationLinkId().toString()); + } else if (service.getCapacityDemand() == 1) { + Assertions.assertEquals(100, service.getServiceDuration(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(TimeWindow.newInstance(5000, 20000), service.getServiceStartTimeWindow()); + locationsPerServiceElement.computeIfAbsent("serviceElement2", (k) -> new HashSet<>()) + .add(service.getLocationLinkId().toString()); + } else if (service.getCapacityDemand() == 2) { + Assertions.assertEquals(200, service.getServiceDuration(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(TimeWindow.newInstance(5000, 20000), service.getServiceStartTimeWindow()); + locationsPerServiceElement.computeIfAbsent("serviceElement2", (k) -> new HashSet<>()) + .add(service.getLocationLinkId().toString()); + } else + Assertions.fail("Service has a wrong demand."); + } + Assertions.assertEquals(12, countDemand); + Assertions.assertEquals(4, countServicesWithCertainDemand.getInt(0)); + Assertions.assertEquals(8, countServicesWithCertainDemand.getInt(1)); + Assertions.assertEquals(2, countServicesWithCertainDemand.getInt(2)); + Assertions.assertEquals(4, locationsPerServiceElement.get("serviceElement1").size()); + for (String locationsOfServiceElement : locationsPerServiceElement.get("serviceElement1")) { + Link link = network.getLinks().get(Id.createLinkId(locationsOfServiceElement)); + Assertions.assertTrue( + FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, null, null)); + Assertions.assertFalse(FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, + new String[] { "area1" }, null)); + Assertions.assertTrue(FreightDemandGenerationUtils.checkPositionInShape(link, null, indexShape, + new String[] { "area2" }, null)); + } + Assertions.assertEquals(4, locationsPerServiceElement.get("serviceElement2").size()); + Assertions.assertTrue(locationsPerServiceElement.get("serviceElement2").contains("i(2,0)")); + + // check carrier 2 + Carrier testCarrier2 = CarriersUtils.getCarriers(scenario).getCarriers() + .get(Id.create("testCarrier2", Carrier.class)); + Assertions.assertEquals(0, testCarrier2.getServices().size()); + Assertions.assertEquals(11, testCarrier2.getShipments().size()); + Object2IntMap countShipmentsWithCertainDemand = new Object2IntOpenHashMap<>(); + Map> locationsPerShipmentElement = new HashMap<>(); + countDemand = 0; + for (CarrierShipment shipment : testCarrier2.getShipments().values()) { + countShipmentsWithCertainDemand.merge((Integer) shipment.getSize(), 1, Integer::sum); + countDemand = countDemand + shipment.getSize(); + if (shipment.getSize() == 0) { + Assertions.assertEquals(300, shipment.getPickupServiceTime(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(350, shipment.getDeliveryServiceTime(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(TimeWindow.newInstance(10000, 45000), shipment.getPickupTimeWindow()); + Assertions.assertEquals(TimeWindow.newInstance(11000, 44000), shipment.getDeliveryTimeWindow()); + locationsPerShipmentElement.computeIfAbsent("ShipmentElement1_pickup", (k) -> new HashSet<>()) + .add(shipment.getFrom().toString()); + locationsPerShipmentElement.computeIfAbsent("ShipmentElement1_delivery", (k) -> new HashSet<>()) + .add(shipment.getTo().toString()); + } else if (shipment.getSize() == 2) { + Assertions.assertEquals(400, shipment.getPickupServiceTime(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(400, shipment.getDeliveryServiceTime(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(TimeWindow.newInstance(11000, 44000), shipment.getPickupTimeWindow()); + Assertions.assertEquals(TimeWindow.newInstance(20000, 40000), shipment.getDeliveryTimeWindow()); + locationsPerShipmentElement.computeIfAbsent("ShipmentElement2_pickup", (k) -> new HashSet<>()) + .add(shipment.getFrom().toString()); + locationsPerShipmentElement.computeIfAbsent("ShipmentElement2_delivery", (k) -> new HashSet<>()) + .add(shipment.getTo().toString()); + } else if (shipment.getSize() == 3) { + Assertions.assertEquals(600, shipment.getPickupServiceTime(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(600, shipment.getDeliveryServiceTime(), MatsimTestUtils.EPSILON); + Assertions.assertEquals(TimeWindow.newInstance(11000, 44000), shipment.getPickupTimeWindow()); + Assertions.assertEquals(TimeWindow.newInstance(20000, 40000), shipment.getDeliveryTimeWindow()); + locationsPerShipmentElement.computeIfAbsent("ShipmentElement2_pickup", (k) -> new HashSet<>()) + .add(shipment.getFrom().toString()); + locationsPerShipmentElement.computeIfAbsent("ShipmentElement2_delivery", (k) -> new HashSet<>()) + .add(shipment.getTo().toString()); + } else + Assertions.fail("Shipment has an unexpected demand."); + } + Assertions.assertEquals(15, countDemand); + Assertions.assertEquals(4, countShipmentsWithCertainDemand.getInt(0)); + Assertions.assertEquals(6, countShipmentsWithCertainDemand.getInt(2)); + Assertions.assertEquals(1, countShipmentsWithCertainDemand.getInt(3)); + Assertions.assertEquals(4, locationsPerShipmentElement.get("ShipmentElement1_pickup").size()); + Assertions.assertEquals(1, locationsPerShipmentElement.get("ShipmentElement1_delivery").size()); + Assertions.assertTrue(locationsPerShipmentElement.get("ShipmentElement1_delivery").contains("i(2,0)")); + Assertions.assertEquals(1, locationsPerShipmentElement.get("ShipmentElement2_pickup").size()); + Assertions.assertEquals(2, locationsPerShipmentElement.get("ShipmentElement2_delivery").size()); + } }