Skip to content

Commit

Permalink
Merge branch 'master' into imc-maintenance3
Browse files Browse the repository at this point in the history
  • Loading branch information
rakow committed Feb 4, 2025
2 parents aae25c1 + 66a65ca commit 43754aa
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 78 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,21 @@ public static boolean allCarriersWithJobsHavePlans(Carriers carriers) {
return true;
}

/**
* Creates a list of carriers with unhandled jobs.
*
* @param carriers the carriers
* @return list of carriers with unhandled jobs
*/
public static List<Carrier> createListOfCarrierWithUnhandledJobs(Carriers carriers) {
List<Carrier> carriersWithUnhandledJobs = new LinkedList<>();
for (Carrier carrier : carriers.getCarriers().values()) {
if (!allJobsHandledBySelectedPlan(carrier))
carriersWithUnhandledJobs.add(carrier);
}
return carriersWithUnhandledJobs;
}

/**
* Checks if a carrier has jobs (services or shipments).
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
package org.matsim.smallScaleCommercialTrafficGeneration;

import com.google.common.base.Joiner;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.matsim.api.core.v01.Scenario;
import org.matsim.core.gbl.MatsimRandom;
import org.matsim.core.utils.io.IOUtils;
import org.matsim.freight.carriers.*;

import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.concurrent.ExecutionException;

public class DefaultUnhandledServicesSolution implements UnhandledServicesSolution {
private static final Logger log = LogManager.getLogger(DefaultUnhandledServicesSolution.class);
private static final Joiner JOIN = Joiner.on("\t");


// Generation data
Random rnd;
Expand All @@ -21,22 +29,13 @@ public class DefaultUnhandledServicesSolution implements UnhandledServicesSoluti
this.generator = generator;
}

public List<Carrier> createListOfCarrierWithUnhandledJobs(Scenario scenario){
List<Carrier> carriersWithUnhandledJobs = new LinkedList<>();
for (Carrier carrier : CarriersUtils.getCarriers(scenario).getCarriers().values()) {
if (!CarriersUtils.allJobsHandledBySelectedPlan(carrier))
carriersWithUnhandledJobs.add(carrier);
}
return carriersWithUnhandledJobs;
}

/**
* Redraws the service-durations of all {@link CarrierService}s of the given {@link Carrier}.
*/
private void redrawAllServiceDurations(Carrier carrier, GenerateSmallScaleCommercialTrafficDemand.CarrierAttributes carrierAttributes, int additionalTravelBufferPerIterationInMinutes) {
for (CarrierService service : carrier.getServices().values()) {
double newServiceDuration = generator.getServiceTimePerStop(carrier, carrierAttributes, additionalTravelBufferPerIterationInMinutes);
CarrierService.Builder builder = CarrierService.Builder.newInstance(service.getId(), service.getServiceLinkId())
CarrierService.Builder builder = CarrierService.Builder.newInstance(service.getId(), service.getServiceLinkId(), 0)
.setServiceDuration(newServiceDuration);
CarrierService redrawnService = builder.setServiceStartingTimeWindow(service.getServiceStaringTimeWindow()).build();
carrier.getServices().put(redrawnService.getId(), redrawnService);
Expand All @@ -47,36 +46,78 @@ private void redrawAllServiceDurations(Carrier carrier, GenerateSmallScaleCommer
public void tryToSolveAllCarriersCompletely(Scenario scenario, List<Carrier> nonCompleteSolvedCarriers) {
int startNumberOfCarriersWithUnhandledJobs = nonCompleteSolvedCarriers.size();
log.info("Starting with carrier-replanning loop.");
for (int i = 0; i < generator.getMaxReplanningIterations(); i++) {
log.info("carrier-replanning loop iteration: {}", i);
int numberOfCarriersWithUnhandledJobs = nonCompleteSolvedCarriers.size();
for (Carrier nonCompleteSolvedCarrier : nonCompleteSolvedCarriers) {
//Delete old plan of carrier
nonCompleteSolvedCarrier.clearPlans();
GenerateSmallScaleCommercialTrafficDemand.CarrierAttributes carrierAttributes = generator.getCarrierId2carrierAttributes().get(nonCompleteSolvedCarrier.getId());

// Generate new services. The new service batch should have a smaller sum of serviceDurations than before (or otherwise it will not change anything)
redrawAllServiceDurations(nonCompleteSolvedCarrier, carrierAttributes, (i + 1) * generator.getAdditionalTravelBufferPerIterationInMinutes());
log.info("Carrier should be changed...");
}
try {
CarriersUtils.runJsprit(scenario, CarriersUtils.CarrierSelectionForSolution.solveOnlyForCarrierWithoutPlans);
} catch (ExecutionException | InterruptedException e) {
throw new RuntimeException(e);

Path outputPath = Path.of(scenario.getConfig().controller().getOutputDirectory(),
"analysis/freight/Carriers_SolvingLoop_stats.tsv");

try (BufferedWriter writer = IOUtils.getBufferedWriter(outputPath.toString())) {
// Write header only if the file is newly created
if (Files.size(outputPath) == 0) {
String[] header = {"iteration", "carriersWithUnhandledJobs", "carriersSolvedInIteration",
"carriersNotSolvedInIteration", "additionalBuffer"};
JOIN.appendTo(writer, header);
writer.newLine();
}

for (int i = 1; i <= generator.getMaxReplanningIterations(); i++) {
log.info("carrier-replanning loop iteration: {}", i);
int numberOfCarriersWithUnhandledJobs = nonCompleteSolvedCarriers.size();

nonCompleteSolvedCarriers = createListOfCarrierWithUnhandledJobs(scenario);
log.info(
"End of carrier-replanning loop iteration: {}. From the {} carriers with unhandled jobs ({} already solved), {} were solved in this iteration with an additionalBuffer of {} minutes.",
i, startNumberOfCarriersWithUnhandledJobs, startNumberOfCarriersWithUnhandledJobs - numberOfCarriersWithUnhandledJobs,
numberOfCarriersWithUnhandledJobs - nonCompleteSolvedCarriers.size(), (i + 1) * generator.getAdditionalTravelBufferPerIterationInMinutes());
if (nonCompleteSolvedCarriers.isEmpty()) break;
}
for (Carrier nonCompleteSolvedCarrier : nonCompleteSolvedCarriers) {
// Delete old plan of carrier
nonCompleteSolvedCarrier.clearPlans();
GenerateSmallScaleCommercialTrafficDemand.CarrierAttributes carrierAttributes =
generator.getCarrierId2carrierAttributes().get(nonCompleteSolvedCarrier.getId());

// Final check
if (!nonCompleteSolvedCarriers.isEmpty()) {
log.warn("Not all services were handled!");
// Generate new services
redrawAllServiceDurations(nonCompleteSolvedCarrier, carrierAttributes,
(i + 1) * generator.getAdditionalTravelBufferPerIterationInMinutes());
}

try {
CarriersUtils.runJsprit(scenario, CarriersUtils.CarrierSelectionForSolution.solveOnlyForCarrierWithoutPlans);
} catch (ExecutionException | InterruptedException e) {
throw new RuntimeException(e);
}

nonCompleteSolvedCarriers = CarriersUtils.createListOfCarrierWithUnhandledJobs(CarriersUtils.getCarriers(scenario));

// Write iteration results to file
JOIN.appendTo(writer, new String[]{String.valueOf(i), String.valueOf(numberOfCarriersWithUnhandledJobs),
String.valueOf(numberOfCarriersWithUnhandledJobs - nonCompleteSolvedCarriers.size()),
String.valueOf(nonCompleteSolvedCarriers.size()),
String.valueOf((i + 1) * generator.getAdditionalTravelBufferPerIterationInMinutes())});
writer.newLine();
writer.flush(); // Ensure it's written immediately

log.info("End of carrier-replanning loop iteration: {}. From the {} carriers with unhandled jobs ({} already solved), {} were solved in this iteration with an additionalBuffer of {} minutes.",
i, startNumberOfCarriersWithUnhandledJobs, startNumberOfCarriersWithUnhandledJobs - numberOfCarriersWithUnhandledJobs,
numberOfCarriersWithUnhandledJobs - nonCompleteSolvedCarriers.size(),
(i + 1) * generator.getAdditionalTravelBufferPerIterationInMinutes());

if (i != 1) {
try {
Files.deleteIfExists(Path.of(
scenario.getConfig().controller().getOutputDirectory(),
scenario.getConfig().controller().getRunId() + ".output_carriers_notCompletelySolved_it_" + (i - 1) + ".xml.gz"));
} catch (IOException e) {
log.warn("Could not delete file: {}/{}.output_carriers_notCompletelySolved_it_{}.xml.gz",
scenario.getConfig().controller().getOutputDirectory(), scenario.getConfig().controller().getRunId(), i);
}
}

if (nonCompleteSolvedCarriers.isEmpty()) break;
else
CarriersUtils.writeCarriers(CarriersUtils.getCarriers(scenario),
scenario.getConfig().controller().getOutputDirectory() + "/" + scenario.getConfig().controller().getRunId() + ".output_carriers_notCompletelySolved_it_" + i + ".xml.gz"
);
}

if (!nonCompleteSolvedCarriers.isEmpty()) {
log.warn("Not all services were handled!");
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
import org.matsim.core.config.Config;
import org.matsim.core.config.ConfigUtils;
import org.matsim.core.config.consistency.UnmaterializedConfigGroupChecker;
import org.matsim.core.config.groups.ControllerConfigGroup;
import org.matsim.core.config.groups.VspExperimentalConfigGroup;
import org.matsim.core.controler.*;
import org.matsim.core.gbl.Gbl;
Expand All @@ -67,7 +66,6 @@
import org.matsim.core.utils.geometry.CoordinateTransformation;
import org.matsim.facilities.ActivityFacility;
import org.matsim.freight.carriers.*;
import org.matsim.freight.carriers.analysis.CarriersAnalysis;
import org.matsim.freight.carriers.controller.*;
import org.matsim.freight.carriers.usecases.chessboard.CarrierTravelDisutilities;
import org.matsim.smallScaleCommercialTrafficGeneration.data.CommercialTourSpecifications;
Expand Down Expand Up @@ -340,7 +338,7 @@ private void filterFacilitiesForZones(Scenario scenario, Map<String, Map<String,

/**
* Solves the generated carrier-plans and puts them into the Scenario.
* If a carrier has unhandled services, a carrier-replanning loop delets the old plans and generates new plans.
* If a carrier has unhandled services, a carrier-replanning loop deletes the old plans and generates new plans.
* The new plans will then be solved and checked again.
* This is repeated until the carrier-plans are solved or the {@code maxReplanningIterations} are reached.
* @param originalScenario complete Scenario
Expand Down Expand Up @@ -467,9 +465,11 @@ private void solveSeparatedVRPs(Scenario originalScenario) throws Exception {
log.info("Solving carriers {}-{} of all {} carriers. This are {} VRP to solve.", fromIndex + 1, toIndex, allCarriers.size(),
subCarriers.size());
CarriersUtils.runJsprit(originalScenario);
List<Carrier> nonCompleteSolvedCarriers = unhandledServicesSolution.createListOfCarrierWithUnhandledJobs(originalScenario);
if (!nonCompleteSolvedCarriers.isEmpty())
unhandledServicesSolution.tryToSolveAllCarriersCompletely(originalScenario, nonCompleteSolvedCarriers);
List<Carrier> nonCompleteSolvedCarriers = CarriersUtils.createListOfCarrierWithUnhandledJobs(CarriersUtils.getCarriers(originalScenario));
if (!nonCompleteSolvedCarriers.isEmpty()) {
CarriersUtils.writeCarriers(CarriersUtils.getCarriers(originalScenario), originalScenario.getConfig().controller().getOutputDirectory() + "/" + originalScenario.getConfig().controller().getRunId() + ".output_carriers_notCompletelySolved.xml.gz");
unhandledServicesSolution.tryToSolveAllCarriersCompletely(originalScenario, nonCompleteSolvedCarriers);
}
solvedCarriers.putAll(CarriersUtils.getCarriers(originalScenario).getCarriers());
CarriersUtils.getCarriers(originalScenario).getCarriers().clear();
if (!splitVRPs)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,12 @@
*/
public interface UnhandledServicesSolution {

/**
* @param scenario Scenario to search for carriers with unhandled jobs
* @return List with the found carriers
*/
List<Carrier> createListOfCarrierWithUnhandledJobs(Scenario scenario);

/**
*
* Checks and recalculates plans of carriers, which did not serve all services.
* This step may take a few minutes.
* @param scenario Scenario to handle the carriers for. Needed to execute {@link org.matsim.freight.carriers.CarriersUtils#runJsprit(Scenario)} and {@link UnhandledServicesSolution#createListOfCarrierWithUnhandledJobs(Scenario)}
* @param nonCompleteSolvedCarriers List of carriers, that are not solved. Can be obtained by {@link UnhandledServicesSolution#createListOfCarrierWithUnhandledJobs(Scenario)}
* @param scenario Scenario to handle the carriers for.
* @param nonCompleteSolvedCarriers List of carriers, that are not solved.
*/
void tryToSolveAllCarriersCompletely(Scenario scenario, List<Carrier> nonCompleteSolvedCarriers);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,11 @@ private double[] calculateTreeForward(int node) {
}
}
}

if(graph.hasTurnRestrictions()) {
consolidateColoredNodes(data);
}

return data;
}

Expand Down Expand Up @@ -296,9 +301,38 @@ private double[] calculateTreeBackward(int node) {
}
}
}

if(graph.hasTurnRestrictions()) {
consolidateColoredNodes(data);
}

return data;
}

private void consolidateColoredNodes(double[] data) {
// update node values with the minimum of their colored copies, if any
for (int i = 0; i < graph.nodeCount; i++) {
Node uncoloredNode = graph.getNode(i);
if (uncoloredNode != null) {

// the index points to a node with a different index -> colored copy
if (uncoloredNode.getId().index() != i) {
int uncoloredIndex = uncoloredNode.getId().index();
double uncoloredCost = data[uncoloredIndex];
double coloredCost = data[i];

if (Double.isFinite(uncoloredCost)) {
if (coloredCost < uncoloredCost) {
data[uncoloredIndex] = coloredCost;
}
} else {
data[uncoloredIndex] = coloredCost;
}
}
}
}
}

int getNodeDeadend(int nodeIndex) {
return this.deadendData[nodeIndex];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,9 @@ public void handleEvent(ActivityEndEvent event) {
activity = firstActivity;
}
activity.setEndTime(event.getTime());
PersonExperiencedActivity personExperiencedActivity = new PersonExperiencedActivity(event.getPersonId(), activity);
for (ActivityHandler activityHandler : this.activityHandlers) {
activityHandler.handleActivity(new PersonExperiencedActivity(event.getPersonId(), activity));
activityHandler.handleActivity(personExperiencedActivity);
}
}

Expand All @@ -107,8 +108,9 @@ public void addActivityHandler(ActivityHandler activityHandler) {

public void finish() {
this.activities.forEach((id, activity) -> {
PersonExperiencedActivity personExperiencedActivity = new PersonExperiencedActivity(id, activity);
for (ActivityHandler activityHandler : this.activityHandlers) {
activityHandler.handleActivity(new PersonExperiencedActivity(id, activity));
activityHandler.handleActivity(personExperiencedActivity);
}
});
}
Expand Down
Loading

0 comments on commit 43754aa

Please sign in to comment.