diff --git a/src/main/java/example/lsp/initialPlans/MyEventBasedCarrierScorer.java b/src/main/java/example/lsp/initialPlans/MyEventBasedCarrierScorer.java index 96f8f04d..8b8b23f6 100644 --- a/src/main/java/example/lsp/initialPlans/MyEventBasedCarrierScorer.java +++ b/src/main/java/example/lsp/initialPlans/MyEventBasedCarrierScorer.java @@ -74,7 +74,7 @@ public EventBasedScoring() { } @Override public void handleEvent(Event event) { - log.warn(event.toString()); + log.debug(event.toString()); if (event instanceof CarrierTourStartEvent freightTourStartEvent) { handleEvent(freightTourStartEvent); } else if (event instanceof CarrierTourEndEvent freightTourEndEvent) { diff --git a/src/main/java/example/lsp/multipleChains/MyEventBasedCarrierScorer.java b/src/main/java/example/lsp/multipleChains/EventBasedCarrierScorer_MultipleChains.java similarity index 61% rename from src/main/java/example/lsp/multipleChains/MyEventBasedCarrierScorer.java rename to src/main/java/example/lsp/multipleChains/EventBasedCarrierScorer_MultipleChains.java index 91801912..47d98eda 100644 --- a/src/main/java/example/lsp/multipleChains/MyEventBasedCarrierScorer.java +++ b/src/main/java/example/lsp/multipleChains/EventBasedCarrierScorer_MultipleChains.java @@ -24,7 +24,7 @@ /** * @author Kai Martins-Turner (kturner) */ -class MyEventBasedCarrierScorer implements CarrierScoringFunctionFactory { +class EventBasedCarrierScorer_MultipleChains implements CarrierScoringFunctionFactory { @Inject private Network network; @@ -74,7 +74,7 @@ public EventBasedScoring() { } @Override public void handleEvent(Event event) { - log.warn(event.toString()); + log.debug(event.toString()); if (event instanceof CarrierTourStartEvent freightTourStartEvent) { handleEvent(freightTourStartEvent); } else if (event instanceof CarrierTourEndEvent freightTourEndEvent) { @@ -124,7 +124,8 @@ class LinkBasedTollScoring implements SumScoringFunction.ArbitraryEventScoring { private final double toll; private double score; - private final List vehicleTypesToBeTolled = Arrays.asList("large50"); +// private final List vehicleTypesToBeTolled = Arrays.asList("large50"); +private final List vehicleTypesToBeTolled = List.of("heavy40t"); private final List> tolledVehicles = new ArrayList<>(); @@ -145,9 +146,24 @@ public LinkBasedTollScoring(double toll) { } } +// private void handleEvent(LinkEnterEvent event) { +// List tolledLinkList = Arrays.asList("i(3,4)", "i(3,6)", "i(7,5)R", "i(7,7)R", "j(4,8)R", "j(6,8)R", "j(3,4)", "j(5,4)"); +// +// final Id vehicleTypeId = (VehicleUtils.findVehicle(event.getVehicleId(), scenario)).getType().getId(); +// +// //toll a vehicle only once. +// if (!tolledVehicles.contains(event.getVehicleId())) +// if (vehicleTypesToBeTolled.contains(vehicleTypeId.toString())) { +// if (tolledLinkList.contains(event.getLinkId().toString())) { +// log.info("Tolling caused by event: " + event); +// tolledVehicles.add(event.getVehicleId()); +// score = score - toll; +// } +// } +// } + private void handleEvent(LinkEnterEvent event) { -// List tolledLinkList = Arrays.asList("i(5,5)R"); - List tolledLinkList = Arrays.asList("i(3,4)", "i(3,6)", "i(7,5)R", "i(7,7)R", "j(4,8)R", "j(6,8)R", "j(3,4)", "j(5,4)"); + List tolledLinkList = Arrays.asList("70831","14691","49319","70830","17284","65008","65007","62413","17283","144164","144165","4606","118311","4607","15423","53820","15422","138286","69167","138287","17057","74648","74647","113641","10307","10306","51775","155051","51776","150042","150043","150164","90583","96329","19320","132511","19321","64851","144180","34042","124770","34041","74891","144184","124769","35018","35017","77379","35256","108717","113640","157261","142799","157262","52995","934","52996","935","95587","95588","17150","147460","147461","54024","54023","152801","144506","145715","144505","156464","17125","17126","114545","114546","140792","17127","17248","17128","17249","156458","35463","159609","35462","159608","22046","154715","22047","144373","154716","155927","155926","144372","96330","61139","98190","144126","144127","61011","61010","156463","63682","47555","73006","94867","138930","94866","133488","138931","47554","73005","58893","116395","116394","144136","1158","1157","58894","61269","79237","144137","732","149702","733","77854","4785","55946","77855","4786","55945","90018","61264","61263","86201","77738","120646","77739","26507","108414","108415","17115","66841","26506","78255","78254","118561","35447","147535","17116","118560","61270","102480","51917","62494","72973","51918","72972","72050","72051","147027","33258","61169","18419","102479","20863","61170","43048","43049","69459","73037","18420","69458","3255","3254","73036","27017","76094","41429","74241","76095","149583","74240","35426","81688","81689","12686","25848","25849","64459","115416","149592","74374","115417","81474","81475","36983","36984","36985","36986","52917","52918","64460","40311","108695","40310","79385","119212","155909","119213","119334","119335","112023","48277","48278","106946","91853","91854","102288","69129","102287","13607","2985","64482","156612","8983","156613","67517","28548","28549","83543","145734","83542","149536","149537","151175","151174","18159","8994","93250","147370","53001","5918","24153","79875","147369","36147","53002","138543","138542","104212","137699","137698","41960","104211","18160","41723","41724","3505","123744","81389","104205","104206","112065","49320","84772","37107","142803"); final Id vehicleTypeId = (VehicleUtils.findVehicle(event.getVehicleId(), scenario)).getType().getId(); diff --git a/src/main/java/example/lsp/multipleChains/ExampleGroceryDeliveryMultipleChains.java b/src/main/java/example/lsp/multipleChains/ExampleGroceryDeliveryMultipleChains.java index 0901880f..72867e96 100644 --- a/src/main/java/example/lsp/multipleChains/ExampleGroceryDeliveryMultipleChains.java +++ b/src/main/java/example/lsp/multipleChains/ExampleGroceryDeliveryMultipleChains.java @@ -3,6 +3,8 @@ import lsp.*; import lsp.resourceImplementations.ResourceImplementationUtils; import lsp.resourceImplementations.distributionCarrier.DistributionCarrierUtils; +import lsp.resourceImplementations.mainRunCarrier.MainRunCarrierUtils; +import lsp.resourceImplementations.transshipmentHub.TranshipmentHubUtils; import lsp.shipment.LSPShipment; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -16,12 +18,14 @@ import org.matsim.contrib.freight.controler.FreightUtils; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.PlanCalcScoreConfigGroup; import org.matsim.core.config.groups.VspExperimentalConfigGroup; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; import org.matsim.core.controler.OutputDirectoryHierarchy; import org.matsim.core.replanning.GenericPlanStrategyImpl; import org.matsim.core.replanning.selectors.BestPlanSelector; +import org.matsim.core.replanning.selectors.ExpBetaPlanSelector; import org.matsim.core.scenario.ScenarioUtils; import org.matsim.vehicles.VehicleType; @@ -34,6 +38,9 @@ public class ExampleGroceryDeliveryMultipleChains { private static final Logger log = LogManager.getLogger(ExampleGroceryDeliveryMultipleChains.class); + static double HUBCOSTS_FIX = 100; + private static final Id HUB_LINK_ID = Id.createLinkId("91085"); + private static final double TOLL_VALUE = 1000; private ExampleGroceryDeliveryMultipleChains() {} @@ -56,7 +63,8 @@ public void install() { controler.addOverridingModule(new AbstractModule() { @Override public void install() { - final MyEventBasedCarrierScorer carrierScorer = new MyEventBasedCarrierScorer(); + final EventBasedCarrierScorer_MultipleChains carrierScorer = new EventBasedCarrierScorer_MultipleChains(); + carrierScorer.setToll(TOLL_VALUE); bind(CarrierScoringFunctionFactory.class).toInstance(carrierScorer); bind(LSPScorerFactory.class).toInstance(MyLSPScorer::new); bind(CarrierStrategyManager.class).toProvider(() -> { @@ -66,7 +74,12 @@ public void install() { }); bind(LSPStrategyManager.class).toProvider(() -> { LSPStrategyManager strategyManager = new LSPStrategyManagerImpl(); - strategyManager.addStrategy(new GenericPlanStrategyImpl<>(new BestPlanSelector<>()), null, 1); + strategyManager.addStrategy(new GenericPlanStrategyImpl<>(new ExpBetaPlanSelector<>(new PlanCalcScoreConfigGroup())), null, 1); +// strategyManager.addStrategy(new RebalancingShipmentsStrategyFactory().createStrategy(), null, 2); +// strategyManager.addStrategy(new RandomShiftingStrategyFactory().createStrategy(), null, 1); +// strategyManager.addStrategy(new ProximityStrategyFactory(scenario.getNetwork()).createStrategy(), null, 1); +// strategyManager.setMaxPlansPerAgent(5); + strategyManager.setPlanSelectorForRemoval(new WorstPlanForRemovalSelector()); return strategyManager; }); } @@ -91,11 +104,10 @@ private static Config prepareConfig(String[] args) { ConfigUtils.applyCommandline(config,args); } else { config.controler().setOutputDirectory("output/groceryDelivery"); - config.controler().setLastIteration(0); + config.controler().setLastIteration(5); } -// config.network().setInputFile("/Users/niclasrichter/Documents/Studium/Master/Thesis/groceryDeliveryScenario/berlin_v5.5-network.xml.gz"); - config.network().setInputFile("https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/berlin/berlin-v5.5-10pct/input/berlin_v5.5-network.xml.gz"); + config.network().setInputFile("https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/berlin/berlin-v5.5-10pct/input/berlin-v5.5-network.xml.gz"); config.controler().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); config.controler().setWriteEventsInterval(1); @@ -115,10 +127,8 @@ private static Scenario prepareScenario(Config config) { } private static LSP createLSP(Scenario scenario) { - - //TODO vielleicht kann man carrier und vehicleTypes auch eleganter direkt von der Website laden - String carrierPlanFile = "/Users/niclasrichter/Documents/Studium/Master/Thesis/groceryDeliveryScenario/CarrierLEH_v2_withFleet_Shipment_OneTW_PickupTime_ICEV.xml"; - String vehicleTypeFile = "/Users/niclasrichter/Documents/Studium/Master/Thesis/groceryDeliveryScenario/vehicleTypesBVWP100_DC_noTax.xml"; + String carrierPlanFile = "https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/berlin/projects/freight/foodRetailing_wo_rangeConstraint/input/CarrierLEH_v2_withFleet_Shipment_OneTW_PickupTime_ICEVandBEV.xml"; + String vehicleTypeFile = "https://svn.vsp.tu-berlin.de/repos/public-svn/matsim/scenarios/countries/de/berlin/projects/freight/foodRetailing_wo_rangeConstraint/input/vehicleTypesBVWP100_DC_noTax.xml"; CarrierVehicleTypes vehicleTypes = new CarrierVehicleTypes(); CarrierVehicleTypeReader vehicleTypeReader = new CarrierVehicleTypeReader(vehicleTypes); @@ -129,43 +139,97 @@ private static LSP createLSP(Scenario scenario) { carrierReader.readFile(carrierPlanFile); Carrier carrier = carriers.getCarriers().get(Id.create("kaufland_VERBRAUCHERMARKT_TROCKEN", CarrierImpl.class)); - // Depotlink vielleicht lieber von den Fahrzeugen nehmen, ist logischer - Id depotLink = carrier.getShipments().values().iterator().next().getFrom(); +// Id depotLinkFromShipments = carrier.getShipments().values().iterator().next().getFrom(); + Id depotLinkFromVehicles = carrier.getCarrierCapabilities().getCarrierVehicles().values().iterator().next().getLinkId(); log.info("create LSP"); - // Create a lsp plan with direct delivery - LSPPlan singleOneEchelonChainPlan; + LSPPlan multipleMixedEchelonChainsPlan; { - LogisticChain singleChain; + LogisticChain directChain; { Carrier singleCarrier = CarrierUtils.createCarrier(Id.create("singleCarrier", Carrier.class)); singleCarrier.getCarrierCapabilities().setFleetSize(CarrierCapabilities.FleetSize.INFINITE); - CarrierUtils.addCarrierVehicle(singleCarrier, CarrierVehicle.newInstance(Id.createVehicleId("singleCarrier"), depotLink, vehicleTypes.getVehicleTypes().get(Id.create("heavy40t", VehicleType.class)))); + CarrierUtils.addCarrierVehicle(singleCarrier, CarrierVehicle.newInstance(Id.createVehicleId("singleCarrier"), depotLinkFromVehicles, vehicleTypes.getVehicleTypes().get(Id.create("heavy40t", VehicleType.class)))); LSPResource singleCarrierResource = DistributionCarrierUtils.DistributionCarrierResourceBuilder.newInstance(singleCarrier, scenario.getNetwork()) .setDistributionScheduler(DistributionCarrierUtils.createDefaultDistributionCarrierScheduler()) .build(); - LogisticChainElement singleCarrierElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("singleCarrierElement", LogisticChainElement.class)) + LogisticChainElement singleCarrierElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("directCarrierElement", LogisticChainElement.class)) .setResource(singleCarrierResource) .build(); - singleChain = LSPUtils.LogisticChainBuilder.newInstance(Id.create("singleChain", LogisticChain.class)) + directChain = LSPUtils.LogisticChainBuilder.newInstance(Id.create("directChain", LogisticChain.class)) .addLogisticChainElement(singleCarrierElement) .build(); } - singleOneEchelonChainPlan = LSPUtils.createLSPPlan() - .addLogisticChain(singleChain) - .setAssigner(MultipleChainsUtils.createPrimaryLogisticChainShipmentAssigner()); + LogisticChain hubChain; + { + Carrier mainCarrier = CarrierUtils.createCarrier(Id.create("mainCarrier", Carrier.class)); + mainCarrier.getCarrierCapabilities().setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarrierUtils.addCarrierVehicle(mainCarrier, CarrierVehicle.newInstance(Id.createVehicleId("mainTruck"), depotLinkFromVehicles, vehicleTypes.getVehicleTypes().get(Id.create("heavy40t", VehicleType.class)))); + LSPResource mainCarrierResource = MainRunCarrierUtils.MainRunCarrierResourceBuilder.newInstance(mainCarrier, scenario.getNetwork()) + .setFromLinkId(depotLinkFromVehicles) + .setMainRunCarrierScheduler(MainRunCarrierUtils.createDefaultMainRunCarrierScheduler()) + .setToLinkId(HUB_LINK_ID) + .setVehicleReturn(ResourceImplementationUtils.VehicleReturn.returnToFromLink) + .build(); + + LogisticChainElement mainCarrierElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("mainCarrierElement", LogisticChainElement.class)) + .setResource(mainCarrierResource) + .build(); + + LSPResourceScheduler hubScheduler = TranshipmentHubUtils.TranshipmentHubSchedulerBuilder.newInstance() + .setCapacityNeedFixed(10) + .setCapacityNeedLinear(1) + .build(); + + LSPResource hubResource = TranshipmentHubUtils.TransshipmentHubBuilder.newInstance(Id.create("Hub", LSPResource.class), HUB_LINK_ID, scenario) + .setTransshipmentHubScheduler(hubScheduler) + .build(); + + LSPUtils.setFixedCost(hubResource, HUBCOSTS_FIX); + + LogisticChainElement hubElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("HubElement", LogisticChainElement.class)) + .setResource(hubResource) + .build(); + + Carrier distributionCarrier = CarrierUtils.createCarrier(Id.create("distributionCarrier", Carrier.class)); + distributionCarrier.getCarrierCapabilities().setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarrierUtils.addCarrierVehicle(distributionCarrier, CarrierVehicle.newInstance(Id.createVehicleId("distributionTruck"), HUB_LINK_ID, vehicleTypes.getVehicleTypes().get(Id.create("heavy40t_electro", VehicleType.class)))); + LSPResource distributionCarrierResource = DistributionCarrierUtils.DistributionCarrierResourceBuilder.newInstance(distributionCarrier, scenario.getNetwork()) + .setDistributionScheduler(DistributionCarrierUtils.createDefaultDistributionCarrierScheduler()) + .build(); + + LogisticChainElement distributionCarrierElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("distributionCarrierElement", LogisticChainElement.class)) + .setResource(distributionCarrierResource) + .build(); + + mainCarrierElement.connectWithNextElement(hubElement); + hubElement.connectWithNextElement(distributionCarrierElement); + + hubChain = LSPUtils.LogisticChainBuilder.newInstance(Id.create("hubChain", LogisticChain.class)) + .addLogisticChainElement(mainCarrierElement) + .addLogisticChainElement(hubElement) + .addLogisticChainElement(distributionCarrierElement) + .build(); + } + + multipleMixedEchelonChainsPlan = LSPUtils.createLSPPlan() + .addLogisticChain(directChain) + .addLogisticChain(hubChain) + .setAssigner(MultipleChainsUtils.createRandomLogisticChainShipmentAssigner()); } List lspPlans = new ArrayList<>(); - lspPlans.add(singleOneEchelonChainPlan); + lspPlans.add(multipleMixedEchelonChainsPlan); LSP lsp = LSPUtils.LSPBuilder.getInstance(Id.create("myLSP", LSP.class)) - .setInitialPlan(singleOneEchelonChainPlan) + .setInitialPlan(multipleMixedEchelonChainsPlan) .setLogisticChainScheduler(ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(createResourcesListFromLSPPlans(lspPlans))) .build(); @@ -178,7 +242,6 @@ private static LSP createLSP(Scenario scenario) { log.info("schedule the LSP with the shipments and according to the scheduler of the Resource"); lsp.scheduleLogisticChains(); - return lsp; } diff --git a/src/main/java/example/lsp/multipleChains/ExampleMultipleMixedEchelonChains.java b/src/main/java/example/lsp/multipleChains/ExampleMultipleMixedEchelonChains.java index 80d4218b..e3e0818c 100644 --- a/src/main/java/example/lsp/multipleChains/ExampleMultipleMixedEchelonChains.java +++ b/src/main/java/example/lsp/multipleChains/ExampleMultipleMixedEchelonChains.java @@ -38,7 +38,7 @@ public class ExampleMultipleMixedEchelonChains { private static final Logger log = LogManager.getLogger(ExampleMultipleMixedEchelonChains.class); - private static final AssignerSetting assignerSetting = AssignerSetting.roundRobin; + private static final AssignerSetting assignerSetting = AssignerSetting.primary; enum AssignerSetting {primary, roundRobin} private static final double TOLL_VALUE = 1000; @@ -86,7 +86,7 @@ public void install() { controler.addOverridingModule(new AbstractModule() { @Override public void install() { - final MyEventBasedCarrierScorer carrierScorer = new MyEventBasedCarrierScorer(); + final EventBasedCarrierScorer_MultipleChains carrierScorer = new EventBasedCarrierScorer_MultipleChains(); bind(CarrierScoringFunctionFactory.class).toInstance(carrierScorer); carrierScorer.setToll(TOLL_VALUE); bind(LSPScorerFactory.class).toInstance( () -> new MyLSPScorer()); @@ -120,8 +120,8 @@ private static Config prepareConfig(String[] args) { } ConfigUtils.applyCommandline(config,args); } else { - config.controler().setOutputDirectory("output/multipleMixedEchelonChains_" + "_" + assignerSetting); - config.controler().setLastIteration(2); + config.controler().setOutputDirectory("output/multipleMixedEchelonChains_" + assignerSetting); + config.controler().setLastIteration(0); } config.network().setInputFile(String.valueOf(IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("freight-chessboard-9x9"), "grid9x9.xml"))); config.controler().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); diff --git a/src/main/java/example/lsp/multipleChains/ExampleMultipleOneEchelonChains.java b/src/main/java/example/lsp/multipleChains/ExampleMultipleOneEchelonChains.java index 87e93bef..4e03ce6c 100644 --- a/src/main/java/example/lsp/multipleChains/ExampleMultipleOneEchelonChains.java +++ b/src/main/java/example/lsp/multipleChains/ExampleMultipleOneEchelonChains.java @@ -81,7 +81,7 @@ public void install() { controler.addOverridingModule(new AbstractModule() { @Override public void install() { - final MyEventBasedCarrierScorer carrierScorer = new MyEventBasedCarrierScorer(); + final EventBasedCarrierScorer_MultipleChains carrierScorer = new EventBasedCarrierScorer_MultipleChains(); bind(CarrierScoringFunctionFactory.class).toInstance(carrierScorer); bind(LSPScorerFactory.class).toInstance(MyLSPScorer::new); bind(CarrierStrategyManager.class).toProvider(() -> { diff --git a/src/main/java/example/lsp/multipleChains/ExampleMultipleOneEchelonChainsReplanning.java b/src/main/java/example/lsp/multipleChains/ExampleMultipleOneEchelonChainsReplanning.java index 387daea9..32cee237 100644 --- a/src/main/java/example/lsp/multipleChains/ExampleMultipleOneEchelonChainsReplanning.java +++ b/src/main/java/example/lsp/multipleChains/ExampleMultipleOneEchelonChainsReplanning.java @@ -80,7 +80,7 @@ public void install() { controler.addOverridingModule(new AbstractModule() { @Override public void install() { - final MyEventBasedCarrierScorer carrierScorer = new MyEventBasedCarrierScorer(); + final EventBasedCarrierScorer_MultipleChains carrierScorer = new EventBasedCarrierScorer_MultipleChains(); bind(CarrierScoringFunctionFactory.class).toInstance(carrierScorer); bind(LSPScorerFactory.class).toInstance(MyLSPScorer::new); bind(CarrierStrategyManager.class).toProvider(() -> { @@ -93,7 +93,7 @@ public void install() { strategyManager.addStrategy(new GenericPlanStrategyImpl<>(new ExpBetaPlanSelector<>(new PlanCalcScoreConfigGroup())), null, 1); // strategyManager.addStrategy(new RoundRobinDistributionAllShipmentsStrategyFactory().createStrategy(), null, 1); // strategyManager.addStrategy(new RandomDistributionAllShipmentsStrategyFactory().createStrategy(), null, 1); - strategyManager.addStrategy(new RebalancingShipmentsStrategyFactory().createStrategy(), null, 2); +// strategyManager.addStrategy(new RebalancingShipmentsStrategyFactory().createStrategy(), null, 1); // strategyManager.addStrategy(new RandomShiftingStrategyFactory().createStrategy(), null, 1); // strategyManager.addStrategy(new ProximityStrategyFactory(scenario.getNetwork()).createStrategy(), null, 1); strategyManager.setMaxPlansPerAgent(5); @@ -124,7 +124,7 @@ private static Config prepareConfig(String[] args) { ConfigUtils.applyCommandline(config,args); } else { config.controler().setOutputDirectory("output/multipleOneEchelonChainsReplanning"); - config.controler().setLastIteration(50); + config.controler().setLastIteration(10); } config.network().setInputFile(String.valueOf(IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("freight-chessboard-9x9"), "grid9x9.xml"))); config.controler().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); diff --git a/src/main/java/example/lsp/multipleChains/ExampleMultipleTwoEchelonChainsReplanning.java b/src/main/java/example/lsp/multipleChains/ExampleMultipleTwoEchelonChainsReplanning.java new file mode 100644 index 00000000..5e9605a2 --- /dev/null +++ b/src/main/java/example/lsp/multipleChains/ExampleMultipleTwoEchelonChainsReplanning.java @@ -0,0 +1,342 @@ +package example.lsp.multipleChains; + +import lsp.*; +import lsp.resourceImplementations.ResourceImplementationUtils; +import lsp.resourceImplementations.distributionCarrier.DistributionCarrierUtils; +import lsp.resourceImplementations.mainRunCarrier.MainRunCarrierUtils; +import lsp.resourceImplementations.transshipmentHub.TranshipmentHubUtils; +import lsp.shipment.LSPShipment; +import lsp.shipment.ShipmentUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.contrib.freight.FreightConfigGroup; +import org.matsim.contrib.freight.carrier.*; +import org.matsim.contrib.freight.controler.CarrierScoringFunctionFactory; +import org.matsim.contrib.freight.controler.CarrierStrategyManager; +import org.matsim.contrib.freight.controler.FreightUtils; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.PlanCalcScoreConfigGroup; +import org.matsim.core.config.groups.VspExperimentalConfigGroup; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controler; +import org.matsim.core.controler.OutputDirectoryHierarchy; +import org.matsim.core.replanning.GenericPlanStrategyImpl; +import org.matsim.core.replanning.selectors.BestPlanSelector; +import org.matsim.core.replanning.selectors.ExpBetaPlanSelector; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.core.utils.io.IOUtils; +import org.matsim.examples.ExamplesUtils; +import org.matsim.vehicles.VehicleType; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +public class ExampleMultipleTwoEchelonChainsReplanning { + + private static final Logger log = LogManager.getLogger(ExampleMultipleTwoEchelonChainsReplanning.class); + + static final double HUBCOSTS_FIX = 100; + + private static final Id DEPOT_LINK_ID = Id.createLinkId("i(5,0)"); + private static final Id HUB_LEFT_LINK_ID = Id.createLinkId("i(1,5)R"); + private static final Id HUB_RIGHT_LINK_ID = Id.createLinkId("j(9,5)"); + + private static final VehicleType VEH_TYPE_SMALL_05 = CarrierVehicleType.Builder.newInstance(Id.create("small05", VehicleType.class)) + .setCapacity(5) + .setMaxVelocity(10) + .setFixCost(5) + .setCostPerDistanceUnit(0.001) + .setCostPerTimeUnit(0.01) + .build(); + + private static final VehicleType VEH_TYPE_LARGE_50 = CarrierVehicleType.Builder.newInstance(Id.create("large50", VehicleType.class)) + .setCapacity(50) + .setMaxVelocity(10) + .setFixCost(150) + .setCostPerDistanceUnit(0.01) + .setCostPerTimeUnit(0.01) + .build(); + + private ExampleMultipleTwoEchelonChainsReplanning() { + } + + public static void main(String[] args) { + log.info("Prepare config"); + Config config = prepareConfig(args); + + log.info("Prepare scenario"); + Scenario scenario = prepareScenario(config); + + log.info("Prepare controler"); + Controler controler = new Controler(scenario); + controler.addOverridingModule(new AbstractModule() { + @Override + public void install() { + install(new LSPModule()); + } + }); + + controler.addOverridingModule(new AbstractModule() { + @Override + public void install() { + final EventBasedCarrierScorer_MultipleChains carrierScorer = new EventBasedCarrierScorer_MultipleChains(); + bind(CarrierScoringFunctionFactory.class).toInstance(carrierScorer); + bind(LSPScorerFactory.class).toInstance(MyLSPScorer::new); + bind(CarrierStrategyManager.class).toProvider(() -> { + CarrierStrategyManager strategyManager = FreightUtils.createDefaultCarrierStrategyManager(); + strategyManager.addStrategy(new GenericPlanStrategyImpl<>(new BestPlanSelector<>()), null, 1); + return strategyManager; + }); + bind(LSPStrategyManager.class).toProvider(() -> { + LSPStrategyManager strategyManager = new LSPStrategyManagerImpl(); + strategyManager.addStrategy(new GenericPlanStrategyImpl<>(new ExpBetaPlanSelector<>(new PlanCalcScoreConfigGroup())), null, 1); + strategyManager.addStrategy(new ProximityStrategyFactory(scenario.getNetwork()).createStrategy(), null, 1); + strategyManager.setMaxPlansPerAgent(5); + strategyManager.setPlanSelectorForRemoval(new WorstPlanForRemovalSelector()); + return strategyManager; + }); + } + }); + + log.info("Run MATSim"); + + //The VSP default settings are designed for person transport simulation. After talking to Kai, they will be set to WARN here. Kai MT may'23 + controler.getConfig().vspExperimental().setVspDefaultsCheckingLevel(VspExperimentalConfigGroup.VspDefaultsCheckingLevel.warn); + controler.run(); + + log.info("Done."); + } + + private static Config prepareConfig(String[] args) { + Config config = ConfigUtils.createConfig(); + if (args.length != 0) { + for (String arg : args) { + log.warn(arg); + } + ConfigUtils.applyCommandline(config,args); + } else { + config.controler().setOutputDirectory("output/multipleTwoEchelonChainsReplanning"); + config.controler().setLastIteration(8); + } + config.network().setInputFile(String.valueOf(IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("freight-chessboard-9x9"), "grid9x9.xml"))); + config.controler().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); + config.controler().setWriteEventsInterval(1); + + FreightConfigGroup freightConfig = ConfigUtils.addOrGetModule(config, FreightConfigGroup.class); + freightConfig.setTimeWindowHandling(FreightConfigGroup.TimeWindowHandling.ignore); + + return config; + } + + private static Scenario prepareScenario(Config config) { + Scenario scenario = ScenarioUtils.loadScenario(config); + + for (Link link : scenario.getNetwork().getLinks().values()) { + link.setFreespeed(30 / 3.6); + link.setCapacity(1000); + } + + log.info("Add LSP to the scenario"); + LSPUtils.addLSPs(scenario, new LSPs(Collections.singletonList(createLSP(scenario)))); + + return scenario; + } + + private static LSP createLSP(Scenario scenario) { + log.info("create LSP"); + Network network = scenario.getNetwork(); + + // A plan with a two hub chains is created + LSPPlan multipleTwoEchelonChainsPlan; + { + LogisticChain hubChainLeft; + { + Carrier mainCarrierLeft = CarrierUtils.createCarrier(Id.create("mainCarrierLeft", Carrier.class)); + mainCarrierLeft.getCarrierCapabilities().setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarrierUtils.addCarrierVehicle(mainCarrierLeft, CarrierVehicle.newInstance(Id.createVehicleId("mainTruck"), DEPOT_LINK_ID, VEH_TYPE_LARGE_50)); + LSPResource mainCarrierResourceLeft = MainRunCarrierUtils.MainRunCarrierResourceBuilder.newInstance(mainCarrierLeft, network) + .setFromLinkId(DEPOT_LINK_ID) + .setMainRunCarrierScheduler(MainRunCarrierUtils.createDefaultMainRunCarrierScheduler()) + .setToLinkId(HUB_LEFT_LINK_ID) + .setVehicleReturn(ResourceImplementationUtils.VehicleReturn.returnToFromLink) + .build(); + + LogisticChainElement mainCarrierElementLeft = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("mainCarrierElementLeft", LogisticChainElement.class)) + .setResource(mainCarrierResourceLeft) + .build(); + + LSPResourceScheduler hubSchedulerLeft = TranshipmentHubUtils.TranshipmentHubSchedulerBuilder.newInstance() + .setCapacityNeedFixed(10) + .setCapacityNeedLinear(1) + .build(); + + LSPResource hubResourceLeft = TranshipmentHubUtils.TransshipmentHubBuilder.newInstance(Id.create("HubLeft", LSPResource.class), HUB_LEFT_LINK_ID, scenario) + .setTransshipmentHubScheduler(hubSchedulerLeft) + .build(); + LSPUtils.setFixedCost(hubResourceLeft, HUBCOSTS_FIX); + + LogisticChainElement hubElementLeft = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("HubElement", LogisticChainElement.class)) + .setResource(hubResourceLeft) + .build(); + + Carrier distributionCarrierLeft = CarrierUtils.createCarrier(Id.create("distributionCarrierLeft", Carrier.class)); + distributionCarrierLeft.getCarrierCapabilities().setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarrierUtils.addCarrierVehicle(distributionCarrierLeft, CarrierVehicle.newInstance(Id.createVehicleId("distributionTruck"), HUB_LEFT_LINK_ID, VEH_TYPE_SMALL_05)); + LSPResource distributionCarrierResourceLeft = DistributionCarrierUtils.DistributionCarrierResourceBuilder.newInstance(distributionCarrierLeft, network) + .setDistributionScheduler(DistributionCarrierUtils.createDefaultDistributionCarrierScheduler()) + .build(); + + LogisticChainElement distributionCarrierElementLeft = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("distributionCarrierElementLeft", LogisticChainElement.class)) + .setResource(distributionCarrierResourceLeft) + .build(); + + mainCarrierElementLeft.connectWithNextElement(hubElementLeft); + hubElementLeft.connectWithNextElement(distributionCarrierElementLeft); + + hubChainLeft = LSPUtils.LogisticChainBuilder.newInstance(Id.create("hubChainLeft", LogisticChain.class)) + .addLogisticChainElement(mainCarrierElementLeft) + .addLogisticChainElement(hubElementLeft) + .addLogisticChainElement(distributionCarrierElementLeft) + .build(); + } + + LogisticChain hubChainRight; + { + Carrier mainCarrier = CarrierUtils.createCarrier(Id.create("mainCarrier", Carrier.class)); + mainCarrier.getCarrierCapabilities().setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarrierUtils.addCarrierVehicle(mainCarrier, CarrierVehicle.newInstance(Id.createVehicleId("mainTruck"), DEPOT_LINK_ID, VEH_TYPE_LARGE_50)); + LSPResource mainCarrierResource = MainRunCarrierUtils.MainRunCarrierResourceBuilder.newInstance(mainCarrier, network) + .setFromLinkId(DEPOT_LINK_ID) + .setMainRunCarrierScheduler(MainRunCarrierUtils.createDefaultMainRunCarrierScheduler()) + .setToLinkId(HUB_RIGHT_LINK_ID) + .setVehicleReturn(ResourceImplementationUtils.VehicleReturn.returnToFromLink) + .build(); + + LogisticChainElement mainCarrierElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("mainCarrierElement", LogisticChainElement.class)) + .setResource(mainCarrierResource) + .build(); + + LSPResourceScheduler hubScheduler = TranshipmentHubUtils.TranshipmentHubSchedulerBuilder.newInstance() + .setCapacityNeedFixed(10) + .setCapacityNeedLinear(1) + .build(); + + LSPResource hubResourceRight = TranshipmentHubUtils.TransshipmentHubBuilder.newInstance(Id.create("HubRight", LSPResource.class), HUB_RIGHT_LINK_ID, scenario) + .setTransshipmentHubScheduler(hubScheduler) + .build(); + LSPUtils.setFixedCost(hubResourceRight, HUBCOSTS_FIX); + + LogisticChainElement hubElementRight = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("HubElement", LogisticChainElement.class)) + .setResource(hubResourceRight) + .build(); + + Carrier distributionCarrier = CarrierUtils.createCarrier(Id.create("distributionCarrier", Carrier.class)); + distributionCarrier.getCarrierCapabilities().setFleetSize(CarrierCapabilities.FleetSize.INFINITE); + + CarrierUtils.addCarrierVehicle(distributionCarrier, CarrierVehicle.newInstance(Id.createVehicleId("distributionTruck"), HUB_RIGHT_LINK_ID, VEH_TYPE_SMALL_05)); + LSPResource distributionCarrierResource = DistributionCarrierUtils.DistributionCarrierResourceBuilder.newInstance(distributionCarrier, network) + .setDistributionScheduler(DistributionCarrierUtils.createDefaultDistributionCarrierScheduler()) + .build(); + + LogisticChainElement distributionCarrierElement = LSPUtils.LogisticChainElementBuilder.newInstance(Id.create("distributionCarrierElement", LogisticChainElement.class)) + .setResource(distributionCarrierResource) + .build(); + + mainCarrierElement.connectWithNextElement(hubElementRight); + hubElementRight.connectWithNextElement(distributionCarrierElement); + + hubChainRight = LSPUtils.LogisticChainBuilder.newInstance(Id.create("hubChainRight", LogisticChain.class)) + .addLogisticChainElement(mainCarrierElement) + .addLogisticChainElement(hubElementRight) + .addLogisticChainElement(distributionCarrierElement) + .build(); + } + + multipleTwoEchelonChainsPlan = LSPUtils.createLSPPlan() + .addLogisticChain(hubChainLeft) + .addLogisticChain(hubChainRight) + .setAssigner(MultipleChainsUtils.createRandomLogisticChainShipmentAssigner()); + } + + List lspPlans = new ArrayList<>(); + lspPlans.add(multipleTwoEchelonChainsPlan); + + LSP lsp = LSPUtils.LSPBuilder.getInstance(Id.create("myLSP", LSP.class)) + .setInitialPlan(multipleTwoEchelonChainsPlan) + .setLogisticChainScheduler(ResourceImplementationUtils.createDefaultSimpleForwardLogisticChainScheduler(createResourcesListFromLSPPlans(lspPlans))) + .build(); + + log.info("create initial LSPShipments"); + log.info("assign the shipments to the LSP"); + for (LSPShipment shipment : createInitialLSPShipments()) { + lsp.assignShipmentToLSP(shipment); + } + + log.info("schedule the LSP with the shipments and according to the scheduler of the Resource"); + lsp.scheduleLogisticChains(); + + return lsp; + } + + private static Collection createInitialLSPShipments() { + List shipmentList = new ArrayList<>(); + int capacityDemand = 1; + + for (int i = 1; i <= 10; i++) { + if (i % 2 != 0) { + Id id = Id.create("ShipmentLeft_" + i, LSPShipment.class); + ShipmentUtils.LSPShipmentBuilder builder = ShipmentUtils.LSPShipmentBuilder.newInstance(id); + + builder.setCapacityDemand(capacityDemand); + builder.setFromLinkId(DEPOT_LINK_ID); + final Id shipmentLeftLinkId = Id.createLinkId("i(1,9)R"); + builder.setToLinkId(shipmentLeftLinkId); + + builder.setEndTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setStartTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setDeliveryServiceTime(capacityDemand * 60); + + shipmentList.add(builder.build()); + } else { + Id id = Id.create("ShipmentRight_" + i, LSPShipment.class); + ShipmentUtils.LSPShipmentBuilder builder = ShipmentUtils.LSPShipmentBuilder.newInstance(id); + + builder.setCapacityDemand(capacityDemand); + builder.setFromLinkId(DEPOT_LINK_ID); + final Id shipmentRightLinkId = Id.createLinkId("j(9,9)"); + builder.setToLinkId(shipmentRightLinkId); + + builder.setEndTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setStartTimeWindow(TimeWindow.newInstance(0, (24 * 3600))); + builder.setDeliveryServiceTime(capacityDemand * 60); + + shipmentList.add(builder.build()); + } + } + return shipmentList; + } + + private static List createResourcesListFromLSPPlans(List lspPlans) { + log.info("Collecting all LSPResources from the LSPPlans"); + List resourceList = new ArrayList<>(); + for (LSPPlan lspPlan : lspPlans) { + for (LogisticChain logisticChain : lspPlan.getLogisticChains()) { + for (LogisticChainElement logisticChainElement : logisticChain.getLogisticChainElements()) { + resourceList.add(logisticChainElement.getResource()); + } + } + } + return resourceList; + } + +} diff --git a/src/main/java/lsp/LSPControlerListener.java b/src/main/java/lsp/LSPControlerListener.java index d20402df..31af1c72 100644 --- a/src/main/java/lsp/LSPControlerListener.java +++ b/src/main/java/lsp/LSPControlerListener.java @@ -128,6 +128,7 @@ public void notifyReplanning(ReplanningEvent event) { strategyManager.run(lsps.getLSPs().values(), event.getIteration(), event.getReplanningContext()); for (LSP lsp : lsps.getLSPs().values()) { + lsp.getSelectedPlan().getShipmentPlans().clear(); //clear ShipmentPlans to start with clear(n) state. Otherwise, some times were accumulating over the time. :( lsp.scheduleLogisticChains(); } diff --git a/src/main/java/lsp/resourceImplementations/distributionCarrier/DistributionCarrierScheduler.java b/src/main/java/lsp/resourceImplementations/distributionCarrier/DistributionCarrierScheduler.java index 75783a86..125128d3 100644 --- a/src/main/java/lsp/resourceImplementations/distributionCarrier/DistributionCarrierScheduler.java +++ b/src/main/java/lsp/resourceImplementations/distributionCarrier/DistributionCarrierScheduler.java @@ -25,6 +25,7 @@ import lsp.resourceImplementations.ResourceImplementationUtils; import lsp.shipment.ShipmentPlanElement; import lsp.shipment.ShipmentUtils; +import org.locationtech.jts.util.Assert; import org.matsim.api.core.v01.Id; import org.matsim.contrib.freight.carrier.*; import org.matsim.contrib.freight.carrier.CarrierCapabilities.FleetSize; @@ -209,12 +210,15 @@ private void addShipmentTransportElement(LspShipmentWithTime tuple, Tour tour, T } } int startIndex = tour.getTourElements().indexOf(tour.getTourElements().indexOf(tour.getStart())); - Leg legAfterStart = (Leg) tour.getTourElements().get(startIndex + 1); - double startTimeOfTransport = legAfterStart.getExpectedDepartureTime(); + final Leg legAfterStart = (Leg) tour.getTourElements().get(startIndex + 1); + final int serviceIndex = tour.getTourElements().indexOf(serviceActivity); + final Leg legBeforeService = (Leg) tour.getTourElements().get(serviceIndex - 1); + final double startTimeOfTransport = legAfterStart.getExpectedDepartureTime(); + final double endTimeOfTransport = legBeforeService.getExpectedTransportTime() + legBeforeService.getExpectedDepartureTime(); + Assert.isTrue(endTimeOfTransport >= startTimeOfTransport, "latest End must be later than earliest start. start: " + startTimeOfTransport + " ; end: " +endTimeOfTransport); + builder.setStartTime(startTimeOfTransport); - int serviceIndex = tour.getTourElements().indexOf(serviceActivity); - Leg legBeforeService = (Leg) tour.getTourElements().get(serviceIndex - 1); - builder.setEndTime(legBeforeService.getExpectedTransportTime() + legBeforeService.getExpectedDepartureTime()); + builder.setEndTime(endTimeOfTransport); builder.setCarrierId(carrier.getId()); builder.setFromLinkId(tour.getStartLinkId()); builder.setToLinkId(serviceActivity.getLocation()); @@ -235,13 +239,18 @@ private void addShipmentUnloadElement(LspShipmentWithTime tuple, Tour tour, Tour } int serviceIndex = tour.getTourElements().indexOf(serviceActivity); ServiceActivity service = (ServiceActivity) tour.getTourElements().get(serviceIndex); - builder.setStartTime(service.getExpectedArrival()); - builder.setEndTime(service.getDuration() + service.getExpectedArrival()); + + final double startTime = service.getExpectedArrival(); + final double endTime = startTime + service.getDuration(); + Assert.isTrue(endTime >= startTime, "latest End must be later than earliest start. start: " + startTime + " ; end: " + endTime); + + builder.setStartTime(startTime); + builder.setEndTime(endTime); builder.setCarrierId(carrier.getId()); builder.setLinkId(serviceActivity.getLocation()); builder.setCarrierService(serviceActivity.getService()); ShipmentPlanElement unload = builder.build(); - String idString = unload.getResourceId() + "" + unload.getLogisticChainElement().getId() + "" + unload.getElementType(); + String idString = unload.getResourceId() + String.valueOf(unload.getLogisticChainElement().getId()) + unload.getElementType(); Id id = Id.create(idString, ShipmentPlanElement.class); ShipmentUtils.getOrCreateShipmentPlan(super.lspPlan, tuple.getShipment().getId()).addPlanElement(id, unload); } diff --git a/src/test/java/example/lsp/multipleChains/MultipleChainsReplanningTest.java b/src/test/java/example/lsp/multipleChains/MultipleChainsReplanningTest.java index a27ccd8b..9e31c0de 100644 --- a/src/test/java/example/lsp/multipleChains/MultipleChainsReplanningTest.java +++ b/src/test/java/example/lsp/multipleChains/MultipleChainsReplanningTest.java @@ -80,7 +80,7 @@ public void install() { controler.addOverridingModule(new AbstractModule() { @Override public void install() { - final MyEventBasedCarrierScorer carrierScorer = new MyEventBasedCarrierScorer(); + final EventBasedCarrierScorer_MultipleChains carrierScorer = new EventBasedCarrierScorer_MultipleChains(); bind(CarrierScoringFunctionFactory.class).toInstance(carrierScorer); bind(LSPScorerFactory.class).toInstance(MyLSPScorer::new); bind(CarrierStrategyManager.class).toProvider(() -> { diff --git a/src/test/java/example/lsp/multipleChains/WorstPlanSelectorTest.java b/src/test/java/example/lsp/multipleChains/WorstPlanSelectorTest.java index e9231012..8a698a33 100644 --- a/src/test/java/example/lsp/multipleChains/WorstPlanSelectorTest.java +++ b/src/test/java/example/lsp/multipleChains/WorstPlanSelectorTest.java @@ -82,7 +82,7 @@ public void install() { controler.addOverridingModule(new AbstractModule() { @Override public void install() { - final MyEventBasedCarrierScorer carrierScorer = new MyEventBasedCarrierScorer(); + final EventBasedCarrierScorer_MultipleChains carrierScorer = new EventBasedCarrierScorer_MultipleChains(); bind(CarrierScoringFunctionFactory.class).toInstance(carrierScorer); bind(LSPScorerFactory.class).toInstance( () -> new MyLSPScorer());