21 package org.matsim.core.population.algorithms;
24 import java.util.stream.Collectors;
26 import org.apache.logging.log4j.LogManager;
27 import org.apache.logging.log4j.Logger;
57 private final List<Trip>
plan;
61 public Candidate(List<Trip> plan,
final Subtour subtour,
final String newTransportMode) {
69 if (
this == o)
return true;
70 if (o == null || getClass() != o.getClass())
return false;
77 return Objects.hash(subtour, newTransportMode);
82 String trips = subtour.
getTrips().stream().map(plan::indexOf).map(String::valueOf).collect(Collectors.joining(
","));
83 return "Candidate[Trips: " + trips +
" -> " + newTransportMode +
"}";
95 private Collection<String>
modes;
115 final String[] modes,
116 final String[] chainBasedModes,
124 final String[] modes,
125 final String[] chainBasedModes,
129 this.modes = Arrays.asList(modes);
130 this.chainBasedModes = Arrays.asList(chainBasedModes);
132 this.probaForChangeSingleTripMode = probaForChooseRandomSingleTripMode;
137 logger.info(
"Chain based modes: " + this.chainBasedModes.toString());
141 if (this.probaForChangeSingleTripMode > 0.) {
142 Collection<String> notChainBasedModes =
new ArrayList<>(this.
modes);
143 notChainBasedModes.removeAll(this.chainBasedModes);
144 final String[] possibleModes = notChainBasedModes.toArray(
new String[]{});
145 if (possibleModes.length >= 2) {
167 this.singleTripSubtourModes = Arrays.asList(singleTripSubtourModes);
178 Collection<String> permissibleModesForThisPlan = permissibleModesCalculator.
getPermissibleModes(plan);
184 permissibleModesForThisPlan);
192 for (String mode : chainBasedModes) {
211 if (this.changeSingleLegMode != null && rng.nextDouble() < this.probaForChangeSingleTripMode &&
hasSingleTripChoice(trips)) {
214 this.tripsToLegs.
run(plan);
215 this.changeSingleLegMode.
run(plan);
223 Collection<String> permissibleModesForThisPlan = permissibleModesCalculator.
getPermissibleModes(plan);
227 List<Candidate> choiceSet =
determineChoiceSet(homeLocation, plan, trips, permissibleModesForThisPlan);
229 if (!choiceSet.isEmpty()) {
230 Candidate whatToDo = choiceSet.get(rng.nextInt(choiceSet.size()));
241 return !trips.stream().map(
243 ).allMatch(chainBasedModes::contains);
249 final List<Trip> trips,
250 final Collection<String> permissibleModesForThisPerson) {
253 final ArrayList<Candidate> choiceSet =
new ArrayList<>();
273 subtour.
getTrips().get(0).getOriginActivity().getFacilityId() != null ?
277 final Collection<String> testingModes =
284 final Set<String> usableChainBasedModes =
new LinkedHashSet<>();
285 for (String mode : testingModes) {
293 if (lastDestination != null) {
296 if (vehicleLocation.
equals(subtourStartLocation)) {
297 usableChainBasedModes.add(mode);
308 Set<String> usableModes =
new LinkedHashSet<>();
310 for (String candidate : permissibleModesForThisPerson) {
311 if (chainBasedModes.contains(candidate)) {
313 if (usableChainBasedModes.contains(candidate)) {
314 usableModes.add(candidate);
318 usableModes.add(candidate);
327 trip-> mode.equals(mainModeIdentifier.
identifyMainMode(trip.getTripElements()))
337 for (String transportMode : usableModes) {
349 if (!modes.contains(mainModeIdentifier.
identifyMainMode(trip.getTripElements()))) {
364 if (firstOrigin == null) {
386 else if ( coordDist > 0 && firstLegUsingMode.
getCoord() != null && lastLegUsingMode.
getCoord() != null)
393 final List<Trip> tripsToSearch,
395 final List<Trip> reversed =
new ArrayList<>(tripsToSearch);
396 Collections.reverse(reversed);
397 for (
Trip trip : reversed) {
398 if (mode.equals(mainModeIdentifier.
identifyMainMode(trip.getTripElements()))) {
399 return trip.getDestinationActivity();
406 final List<Trip> tripsToSearch,
408 for (
Trip trip : tripsToSearch) {
409 if (mode.equals(mainModeIdentifier.
identifyMainMode(trip.getTripElements()))) {
410 return trip.getOriginActivity();
418 subtour.
getTrips().get(0).getTripElements());
425 boolean containsChainBasedMode =
false;
426 Set<String> originalModes =
new HashSet<>();
433 String mainMode = mainModeIdentifier.
identifyMainMode(trip.getTripElements());
435 if (childTrips.contains(trip) && chainBasedModes.contains(mainMode))
436 containsChainBasedMode =
true;
438 if (childTrips.contains(trip))
439 originalModes.add(mainMode);
442 if (!modes.contains(mainMode)) {
450 trip.getOriginActivity(),
452 trip.getDestinationActivity());
459 && containsChainBasedMode && originalModes.size() > 1
462 logger.error(
"Subtour of person {} contains a mix of chain- and non-chainbased modes: {}. " +
463 "Subtour mode-choice won't be able to go back to this state. You need to adjust the input beforehand or disable 'betweenAllAndFewerConstraints'.", plan.
getPerson().getId(), originalModes);
464 throw new IllegalStateException(
"Subtour contains a mix of chain- and non-chainbased modes.");
Collection< String > getPermissibleModes(Plan plan)
final Collection< String > chainBasedModes
void run(final Plan plan)
static Subtour getUnclosedRootSubtour(final Plan plan)
boolean atSameLocation(Activity firstLegUsingMode, Activity lastLegUsingMode)
Activity findFirstOriginOfMode(final List< Trip > tripsToSearch, final String mode)
boolean isMassConserving(final Subtour subtour, final String mode)
final MainModeIdentifier mainModeIdentifier
boolean hasSingleTripChoice(List< Trip > trips)
Id<? extends BasicLocation > getLocationId(Activity activity)
ChooseRandomLegModeForSubtour(final MainModeIdentifier mainModeIdentifier, final PermissibleModesCalculator permissibleModesCalculator, final String[] modes, final String[] chainBasedModes, final Random rng, SubtourModeChoice.Behavior behavior, double probaForChooseRandomSingleTripMode, double coordDist)
static double calcEuclideanDistance(Coord coord, Coord other)
String getTransportMode(final Subtour subtour)
void run(final Plan plan)
static List< PlanElement > insertTrip(final Plan plan, final Activity origin, final List<? extends PlanElement > trip, final Activity destination)
ChooseRandomSingleLegMode changeSingleLegMode
TripsToLegsAlgorithm tripsToLegs
String identifyMainMode(List<? extends PlanElement > tripElements)
ChooseRandomLegModeForSubtour(final MainModeIdentifier mainModeIdentifier, final PermissibleModesCalculator permissibleModesCalculator, final String[] modes, final String[] chainBasedModes, final Random rng, SubtourModeChoice.Behavior behavior, double probaForChooseRandomSingleTripMode)
void applyChange(final Candidate whatToDo, final Plan plan)
Collection< String > singleTripSubtourModes
Activity findLastDestinationOfMode(final List< Trip > tripsToSearch, final String mode)
final double probaForChangeSingleTripMode
static final Logger logger
List< Candidate > determineChoiceSet(final Plan plan)
PermissibleModesCalculator permissibleModesCalculator
boolean equals(final Object other)
boolean containsUnknownMode(final Subtour subtour)
static Leg createLeg(String transportMode)
static List< Trip > getTrips(final Plan plan)
List< PlanElement > getPlanElements()
List< Trip > getTripsWithoutSubSubtours()
boolean isMassConserving(final Subtour subtour)
static Collection< Subtour > getSubtours(final Plan plan)
fromSpecifiedModesToSpecifiedModes
final String newTransportMode
Id< ActivityFacility > getFacilityId()
betweenAllAndFewerConstraints
Candidate(List< Trip > plan, final Subtour subtour, final String newTransportMode)
String getNewTransportMode()
void run(final Plan plan)
boolean equals(Object obj)
final SubtourModeChoice.Behavior behavior
Collection< String > modes
void setSingleTripSubtourModes(final String[] singleTripSubtourModes)
List< Candidate > determineChoiceSet(final Id<? extends BasicLocation > homeLocation, final Plan plan, final List< Trip > trips, final Collection< String > permissibleModesForThisPerson)