Skip to content

Commit

Permalink
Merge branch 'master' into dependabot/maven/org.apache.commons-common…
Browse files Browse the repository at this point in the history
…s-compress-1.27.1
  • Loading branch information
jfbischoff authored Sep 8, 2024
2 parents c941086 + 7cc2825 commit f2a4fab
Show file tree
Hide file tree
Showing 5 changed files with 204 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public class DiscreteModeChoiceModule extends AbstractModule {
@Override
public void install() {
addPlanStrategyBinding(STRATEGY_NAME).toProvider(DiscreteModeChoiceStrategyProvider.class);
addControlerListenerBinding().to(UtilitiesWriterHandler.class);

if (getConfig().replanning().getPlanSelectorForRemoval().equals(NonSelectedPlanSelector.NAME)) {
bindPlanSelectorForRemoval().to(NonSelectedPlanSelector.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package org.matsim.contribs.discrete_mode_choice.modules;

import com.google.inject.Inject;
import org.matsim.api.core.v01.population.Population;
import org.matsim.contribs.discrete_mode_choice.modules.config.DiscreteModeChoiceConfigGroup;
import org.matsim.contribs.discrete_mode_choice.modules.utils.ExtractPlanUtilities;
import org.matsim.core.config.groups.ControllerConfigGroup;
import org.matsim.core.controler.OutputDirectoryHierarchy;
import org.matsim.core.controler.events.IterationStartsEvent;
import org.matsim.core.controler.events.ShutdownEvent;
import org.matsim.core.controler.listener.IterationStartsListener;
import org.matsim.core.controler.listener.ShutdownListener;

import java.io.IOException;

public class UtilitiesWriterHandler implements ShutdownListener, IterationStartsListener {
private final OutputDirectoryHierarchy outputDirectoryHierarchy;
private final ControllerConfigGroup controllerConfigGroup;
private final Population population;
private final DiscreteModeChoiceConfigGroup discreteModeChoiceConfigGroup;

@Inject
public UtilitiesWriterHandler(ControllerConfigGroup controllerConfigGroup, DiscreteModeChoiceConfigGroup discreteModeChoiceConfigGroup, Population population, OutputDirectoryHierarchy outputDirectoryHierarchy) {
this.controllerConfigGroup = controllerConfigGroup;
this.discreteModeChoiceConfigGroup = discreteModeChoiceConfigGroup;
this.population = population;
this.outputDirectoryHierarchy = outputDirectoryHierarchy;
}

@Override
public void notifyShutdown(ShutdownEvent event) {
String filePath = this.outputDirectoryHierarchy.getOutputFilename("dmc_utilities.csv");
try {
ExtractPlanUtilities.writePlanUtilities(population, filePath);
} catch (IOException e) {
throw new RuntimeException(e);
}
}

@Override
public void notifyIterationStarts(IterationStartsEvent event) {
if(event.getIteration() == controllerConfigGroup.getFirstIteration() || this.discreteModeChoiceConfigGroup.getWriteUtilitiesInterval() % event.getIteration() != 0) {
return;
}
String filePath = this.outputDirectoryHierarchy.getIterationFilename(event.getIteration(), "dmc_utilities.csv");
try {
ExtractPlanUtilities.writePlanUtilities(population, filePath);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.util.Map;
import java.util.stream.Collectors;

import jakarta.validation.constraints.Positive;
import org.matsim.contribs.discrete_mode_choice.model.DiscreteModeChoiceModel;
import org.matsim.contribs.discrete_mode_choice.model.DiscreteModeChoiceModel.FallbackBehaviour;
import org.matsim.contribs.discrete_mode_choice.modules.ConstraintModule;
Expand All @@ -27,7 +28,7 @@

/**
* Main config group for the DiscreteModeChoice extension.
*
*
* @author sebhoerl
*/
public class DiscreteModeChoiceConfigGroup extends ReflectiveConfigGroup {
Expand All @@ -53,7 +54,8 @@ public class DiscreteModeChoiceConfigGroup extends ReflectiveConfigGroup {
private Collection<String> tripFilters = new HashSet<>();

private Collection<String> cachedModes = new HashSet<>();

@Positive
private int writeUtilitiesInterval = 1;
public static final String GROUP_NAME = "DiscreteModeChoice";

public static final String PERFORM_REROUTE = "performReroute";
Expand Down Expand Up @@ -110,6 +112,9 @@ public class DiscreteModeChoiceConfigGroup extends ReflectiveConfigGroup {
public static final String CACHED_MODES = "cachedModes";
public static final String CACHED_MODES_CMT = "Trips tested with the modes listed here will be cached for each combination of trip and agent during one replanning pass.";

public static final String WRITE_UTILITIES_INTERVAL = "writeUtilitiesInterval";
public static final String WRITE_UTILITIES_INTERVAL_CMT = "Specifies the interval, in iterations, at which the dmc_utilities.csv file is written. If set to 0, the file is written only at the end of the simulation";

public DiscreteModeChoiceConfigGroup() {
super(GROUP_NAME);
}
Expand Down Expand Up @@ -436,6 +441,22 @@ public String getCachedModesAsString() {
return String.join(", ", cachedModes);
}

/**
* @param writeUtilitiesInterval -- {@value #WRITE_UTILITIES_INTERVAL_CMT}
*/
@StringSetter(WRITE_UTILITIES_INTERVAL)
public void setWriteUtilitiesInterval(int writeUtilitiesInterval) {
this.writeUtilitiesInterval = writeUtilitiesInterval;
}

/**
* @return -- {@value #WRITE_UTILITIES_INTERVAL_CMT}
*/
@StringGetter(WRITE_UTILITIES_INTERVAL)
public int getWriteUtilitiesInterval() {
return this.writeUtilitiesInterval;
}

// --- Component configuration ---

private final Map<Tuple<String, String>, ConfigGroup> componentRegistry = createComponentRegistry(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package org.matsim.contribs.discrete_mode_choice.modules.utils;

import org.matsim.api.core.v01.Scenario;
import org.matsim.api.core.v01.population.Person;
import org.matsim.api.core.v01.population.Plan;
import org.matsim.api.core.v01.population.Population;
import org.matsim.core.config.CommandLine;
import org.matsim.core.config.Config;
import org.matsim.core.config.ConfigUtils;
import org.matsim.core.population.io.PopulationReader;
import org.matsim.core.scenario.ScenarioUtils;

import java.io.FileWriter;
import java.io.IOException;

public class ExtractPlanUtilities {
public static void writePlanUtilities(Population population, String filePath) throws IOException {
FileWriter writer = new FileWriter(filePath);
writer.write(String.join(CSV_SEPARATOR, CSV_HEADER));
writer.write("\n");

for(Person person: population.getPersons().values()) {
double utility = Double.NaN;
Plan plan = person.getSelectedPlan();
if(plan != null && plan.getAttributes().getAttribute("utility") != null) {
utility = (double) plan.getAttributes().getAttribute("utility");
}
writer.write(String.join(CSV_SEPARATOR, new String[]{
person.getId().toString(),
String.valueOf(utility)
}));
writer.write("\n");
}
writer.close();
}

public static final String CMD_PLANS_PATH = "plans-path";
public static final String CMD_OUTPUT_PATH = "output-path";
public static final String CSV_SEPARATOR = ";";
public static final String[] CSV_HEADER = new String[]{"person_id", "utility"};

public static void main(String[] args) throws CommandLine.ConfigurationException, IOException {
CommandLine commandLine = new CommandLine.Builder(args).requireOptions(CMD_PLANS_PATH, CMD_OUTPUT_PATH).build();

Config config = ConfigUtils.createConfig();
Scenario scenario = ScenarioUtils.createScenario(config);
new PopulationReader(scenario).readFile(commandLine.getOptionStrict(CMD_PLANS_PATH));

writePlanUtilities(scenario.getPopulation(), commandLine.getOptionStrict(CMD_OUTPUT_PATH));
}
}
Original file line number Diff line number Diff line change
@@ -1,75 +1,77 @@
package org.matsim.contribs.discrete_mode_choice.replanning;

import java.util.Collections;
import java.util.List;
import java.util.Random;

import org.matsim.api.core.v01.population.Leg;
import org.matsim.api.core.v01.population.Plan;
import org.matsim.api.core.v01.population.PlanElement;
import org.matsim.api.core.v01.population.PopulationFactory;
import org.matsim.contribs.discrete_mode_choice.model.DiscreteModeChoiceModel;
import org.matsim.contribs.discrete_mode_choice.model.DiscreteModeChoiceTrip;
import org.matsim.contribs.discrete_mode_choice.model.DiscreteModeChoiceModel.NoFeasibleChoiceException;
import org.matsim.contribs.discrete_mode_choice.model.trip_based.candidates.RoutedTripCandidate;
import org.matsim.contribs.discrete_mode_choice.model.trip_based.candidates.TripCandidate;
import org.matsim.core.population.algorithms.PlanAlgorithm;
import org.matsim.core.router.TripRouter;

/**
* This replanning algorithm uses a predefined discrete mode choice model to
* perform mode decisions for a given plan.
*
* @author sebhoerl
*/
public class DiscreteModeChoiceAlgorithm implements PlanAlgorithm {
private final Random random;
private final DiscreteModeChoiceModel modeChoiceModel;
private final TripListConverter tripListConverter;

private final PopulationFactory populationFactory;

public DiscreteModeChoiceAlgorithm(Random random, DiscreteModeChoiceModel modeChoiceModel,
PopulationFactory populationFactory, TripListConverter tripListConverter) {
this.random = random;
this.modeChoiceModel = modeChoiceModel;
this.populationFactory = populationFactory;
this.tripListConverter = tripListConverter;
}

@Override
/**
* Performs mode choice on a plan. We assume that TripsToLegs has been called
* before, hence the code is working diretly on legs.
*/
public void run(Plan plan) {
// I) First build a list of DiscreteModeChoiceTrips
List<DiscreteModeChoiceTrip> trips = tripListConverter.convert(plan);

// II) Run mode choice

try {
// Perform mode choice and retrieve candidates
List<TripCandidate> chosenCandidates = modeChoiceModel.chooseModes(plan.getPerson(), trips, random);

for (int i = 0; i < trips.size(); i++) {
DiscreteModeChoiceTrip trip = trips.get(i);
TripCandidate candidate = chosenCandidates.get(i);

List<? extends PlanElement> insertElements;

if (candidate instanceof RoutedTripCandidate) {
RoutedTripCandidate routedCandidate = (RoutedTripCandidate) candidate;
insertElements = routedCandidate.getRoutedPlanElements();
} else {
Leg insertLeg = populationFactory.createLeg(candidate.getMode());
insertElements = Collections.singletonList(insertLeg);
}

TripRouter.insertTrip(plan, trip.getOriginActivity(), insertElements, trip.getDestinationActivity());
}
} catch (NoFeasibleChoiceException e) {
throw new IllegalStateException(e);
}
}
}
package org.matsim.contribs.discrete_mode_choice.replanning;

import java.util.Collections;
import java.util.List;
import java.util.Random;

import org.matsim.api.core.v01.population.Leg;
import org.matsim.api.core.v01.population.Plan;
import org.matsim.api.core.v01.population.PlanElement;
import org.matsim.api.core.v01.population.PopulationFactory;
import org.matsim.contribs.discrete_mode_choice.model.DiscreteModeChoiceModel;
import org.matsim.contribs.discrete_mode_choice.model.DiscreteModeChoiceTrip;
import org.matsim.contribs.discrete_mode_choice.model.DiscreteModeChoiceModel.NoFeasibleChoiceException;
import org.matsim.contribs.discrete_mode_choice.model.trip_based.candidates.RoutedTripCandidate;
import org.matsim.contribs.discrete_mode_choice.model.trip_based.candidates.TripCandidate;
import org.matsim.contribs.discrete_mode_choice.model.utilities.UtilityCandidate;
import org.matsim.core.population.algorithms.PlanAlgorithm;
import org.matsim.core.router.TripRouter;

/**
* This replanning algorithm uses a predefined discrete mode choice model to
* perform mode decisions for a given plan.
*
* @author sebhoerl
*/
public class DiscreteModeChoiceAlgorithm implements PlanAlgorithm {
private final Random random;
private final DiscreteModeChoiceModel modeChoiceModel;
private final TripListConverter tripListConverter;

private final PopulationFactory populationFactory;

public DiscreteModeChoiceAlgorithm(Random random, DiscreteModeChoiceModel modeChoiceModel,
PopulationFactory populationFactory, TripListConverter tripListConverter) {
this.random = random;
this.modeChoiceModel = modeChoiceModel;
this.populationFactory = populationFactory;
this.tripListConverter = tripListConverter;
}

@Override
/**
* Performs mode choice on a plan. We assume that TripsToLegs has been called
* before, hence the code is working diretly on legs.
*/
public void run(Plan plan) {
// I) First build a list of DiscreteModeChoiceTrips
List<DiscreteModeChoiceTrip> trips = tripListConverter.convert(plan);

// II) Run mode choice

try {
// Perform mode choice and retrieve candidates
List<TripCandidate> chosenCandidates = modeChoiceModel.chooseModes(plan.getPerson(), trips, random);

for (int i = 0; i < trips.size(); i++) {
DiscreteModeChoiceTrip trip = trips.get(i);
TripCandidate candidate = chosenCandidates.get(i);

List<? extends PlanElement> insertElements;

if (candidate instanceof RoutedTripCandidate) {
RoutedTripCandidate routedCandidate = (RoutedTripCandidate) candidate;
insertElements = routedCandidate.getRoutedPlanElements();
} else {
Leg insertLeg = populationFactory.createLeg(candidate.getMode());
insertElements = Collections.singletonList(insertLeg);
}

TripRouter.insertTrip(plan, trip.getOriginActivity(), insertElements, trip.getDestinationActivity());
}
plan.getAttributes().putAttribute("utility", chosenCandidates.stream().mapToDouble(UtilityCandidate::getUtility).sum());
} catch (NoFeasibleChoiceException e) {
throw new IllegalStateException(e);
}
}
}

0 comments on commit f2a4fab

Please sign in to comment.