From 712783e9d8bcf0849f6b1e03c0471181428ab199 Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Tue, 23 Apr 2024 13:48:45 +0200 Subject: [PATCH] add executor service --- .../freight/carriers/CarriersUtils.java | 106 +++++++++++------- 1 file changed, 64 insertions(+), 42 deletions(-) diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarriersUtils.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarriersUtils.java index 755be732e4d..7cb9c00204c 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/CarriersUtils.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/CarriersUtils.java @@ -46,6 +46,8 @@ import javax.management.InvalidAttributeValueException; import java.util.*; import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; @@ -192,7 +194,7 @@ public static void runJsprit(Scenario scenario) throws ExecutionException, Inter // Fill carrierActivityCounterMap -> basis for sorting the carriers by number of activities before solving in parallel for (Carrier carrier : carriers.getCarriers().values()) { carrierActivityCounterMap.put(carrier.getId(), carrierActivityCounterMap.getOrDefault(carrier.getId(), 0) + carrier.getServices().size()); - carrierActivityCounterMap.put(carrier.getId(), carrierActivityCounterMap.getOrDefault(carrier.getId(), 0) + carrier.getShipments().size()); + carrierActivityCounterMap.put(carrier.getId(), carrierActivityCounterMap.getOrDefault(carrier.getId(), 0) + 2*carrier.getShipments().size()); } HashMap, Integer> sortedMap = carrierActivityCounterMap.entrySet().stream() @@ -203,53 +205,73 @@ public static void runJsprit(Scenario scenario) throws ExecutionException, Inter AtomicInteger solvedVRPCounter = new AtomicInteger(0); ArrayList> tempList = new ArrayList<>(sortedMap.keySet()); - ForkJoinPool forkJoinPool = new ForkJoinPool(Runtime.getRuntime().availableProcessors()); - forkJoinPool.submit(() -> tempList.parallelStream().forEach(carrierId -> { - Carrier carrier = carriers.getCarriers().get(carrierId); - - double start = System.currentTimeMillis(); - if (!carrier.getServices().isEmpty()) - log.info("Start tour planning for {} which has {} services", carrier.getId(), carrier.getServices().size()); - else if (!carrier.getShipments().isEmpty()) - log.info("Start tour planning for {} which has {} shipments", carrier.getId(), carrier.getShipments().size()); - - startedVRPCounter.incrementAndGet(); - log.info("started VRP solving for carrier number {} out of {} carriers.", startedVRPCounter.get(), carriers.getCarriers().size()); - - VehicleRoutingProblem problem = MatsimJspritFactory.createRoutingProblemBuilder(carrier, scenario.getNetwork()).setRoutingCost(netBasedCosts).build(); - VehicleRoutingAlgorithm algorithm = MatsimJspritFactory.loadOrCreateVehicleRoutingAlgorithm(scenario, freightCarriersConfigGroup, netBasedCosts, problem); - - algorithm.getAlgorithmListeners().addListener(new StopWatch(), VehicleRoutingAlgorithmListeners.Priority.HIGH); - int jspritIterations = getJspritIterations(carrier); - try { - if (jspritIterations > 0) { - algorithm.setMaxIterations(jspritIterations); - } else { - throw new InvalidAttributeValueException( - "Carrier has invalid number of jsprit iterations. They must be positive! Carrier id: " - + carrier.getId().toString());} - } catch (Exception e) { - throw new RuntimeException(e); -// e.printStackTrace(); - } - VehicleRoutingProblemSolution solution = Solutions.bestOf(algorithm.searchSolutions()); + int nThreads = Runtime.getRuntime().availableProcessors(); + ExecutorService executorService = Executors.newFixedThreadPool(nThreads); + List>> splitList = splitListAlternating(nThreads, tempList); + for (List> subList : splitList) { + executorService.submit(() -> subList.forEach(carrierId -> { + Carrier carrier = carriers.getCarriers().get(carrierId); + + double start = System.currentTimeMillis(); + if (!carrier.getServices().isEmpty()) + log.info("Start tour planning for {} which has {} services", carrier.getId(), carrier.getServices().size()); + else if (!carrier.getShipments().isEmpty()) + log.info("Start tour planning for {} which has {} shipments", carrier.getId(), carrier.getShipments().size()); + + startedVRPCounter.incrementAndGet(); + log.info("started VRP solving for carrier number {} out of {} carriers.", startedVRPCounter.get(), carriers.getCarriers().size()); + + VehicleRoutingProblem problem = MatsimJspritFactory.createRoutingProblemBuilder(carrier, scenario.getNetwork()).setRoutingCost(netBasedCosts).build(); + VehicleRoutingAlgorithm algorithm = MatsimJspritFactory.loadOrCreateVehicleRoutingAlgorithm(scenario, freightCarriersConfigGroup, netBasedCosts, problem); + + algorithm.getAlgorithmListeners().addListener(new StopWatch(), VehicleRoutingAlgorithmListeners.Priority.HIGH); + int jspritIterations = getJspritIterations(carrier); + try { + if (jspritIterations > 0) { + algorithm.setMaxIterations(jspritIterations); + } else { + throw new InvalidAttributeValueException( + "Carrier has invalid number of jsprit iterations. They must be positive! Carrier id: " + + carrier.getId().toString());} + } catch (Exception e) { + throw new RuntimeException(e); + // e.printStackTrace(); + } + + VehicleRoutingProblemSolution solution = Solutions.bestOf(algorithm.searchSolutions()); + + log.info("tour planning for carrier {} took {} seconds.", carrier.getId(), (System.currentTimeMillis() - start) / 1000); - log.info("tour planning for carrier {} took {} seconds.", carrier.getId(), (System.currentTimeMillis() - start) / 1000); + CarrierPlan newPlan = MatsimJspritFactory.createPlan(carrier, solution); + // yy In principle, the carrier should know the vehicle types that it can deploy. - CarrierPlan newPlan = MatsimJspritFactory.createPlan(carrier, solution); - // yy In principle, the carrier should know the vehicle types that it can deploy. + log.info("routing plan for carrier {}", carrier.getId()); + NetworkRouter.routePlan(newPlan, netBasedCosts); + solvedVRPCounter.incrementAndGet(); + log.info("routing for carrier {} finished. Tour planning plus routing took {} seconds.", carrier.getId(), + (System.currentTimeMillis() - start) / 1000); + log.info("solved {} out of {} carriers.", solvedVRPCounter.get(), carriers.getCarriers().size()); - log.info("routing plan for carrier {}", carrier.getId()); - NetworkRouter.routePlan(newPlan, netBasedCosts); - solvedVRPCounter.incrementAndGet(); - log.info("routing for carrier {} finished. Tour planning plus routing took {} seconds.", carrier.getId(), - (System.currentTimeMillis() - start) / 1000); - log.info("solved {} out of {} carriers.", solvedVRPCounter.get(), carriers.getCarriers().size()); + carrier.setSelectedPlan(newPlan); + })).get(); + } + } - carrier.setSelectedPlan(newPlan); - })).get(); + // split tempList in nThreads parts such that it is split to 1,2,...,n,1,2,.. + private static List>> splitListAlternating(int nThreads, ArrayList> tempList) { + List>> splitList = new ArrayList<>(); + for (int i = 0; i < nThreads; i++) { + List> subList = new ArrayList<>(); + for (int j = i; j < tempList.size(); j += nThreads) { + subList.add(tempList.get(j)); + } + splitList.add(subList); + } + assert splitList.size() == nThreads; + assert splitList.stream().mapToInt(List::size).sum() == tempList.size(); + return splitList; } /**