MATSIM
ChooseRandomLegMode.java
Go to the documentation of this file.
1 /* *********************************************************************** *
2  * project: org.matsim.*
3  * ChangeLegMode.java
4  * *
5  * *********************************************************************** *
6  * *
7  * copyright : (C) 2008 by the members listed in the COPYING, *
8  * LICENSE and WARRANTY file. *
9  * email : info at matsim dot org *
10  * *
11  * *********************************************************************** *
12  * *
13  * This program is free software; you can redistribute it and/or modify *
14  * it under the terms of the GNU General Public License as published by *
15  * the Free Software Foundation; either version 2 of the License, or *
16  * (at your option) any later version. *
17  * See also COPYING, LICENSE and WARRANTY file *
18  * *
19  * *********************************************************************** */
20 
21 package org.matsim.core.population.algorithms;
22 
32 
33 import java.util.List;
34 import java.util.Random;
35 
43 public final class ChooseRandomLegMode implements PlanAlgorithm {
44 
45  private final String[] possibleModes;
46  private boolean ignoreCarAvailability = true;
48  private final Random rng;
49 
57  public ChooseRandomLegMode(final String[] possibleModes, final Random rng, boolean allowSwitchFromListedModesOnly) {
58  this.possibleModes = possibleModes.clone();
59  this.allowSwitchFromListedModesOnly = allowSwitchFromListedModesOnly;
60  this.rng = rng;
61  }
62 
63  public void setIgnoreCarAvailability(final boolean ignoreCarAvailability) {
64  this.ignoreCarAvailability = ignoreCarAvailability;
65  }
66 
67  @Override
68  public void run(final Plan plan) {
69  List<PlanElement> tour = plan.getPlanElements();
70  changeToRandomLegMode(tour, plan);
71  }
72 
73  private void changeToRandomLegMode(final List<PlanElement> tour, final Plan plan) {
74  if (tour.size() > 1) {
75  boolean forbidCar = false;
76  if (!this.ignoreCarAvailability) {
77  String carAvail = PersonUtils.getCarAvail(plan.getPerson());
78  if ("never".equals(carAvail)) {
79  forbidCar = true;
80  }
81  }
82 
83  final String currentMode = getTransportMode(tour);
84  if (this.allowSwitchFromListedModesOnly){
85  if (!contains(this.possibleModes, currentMode)) {
86  return;
87  }
88  }
89  String newMode;
90 
91  while (true) {
92  int newModeIdx = chooseModeOtherThan(currentMode);
93  newMode = this.possibleModes[newModeIdx];
94  if (!(forbidCar && TransportMode.car.equals(newMode))) {
95  break;
96  } else {
97  if (this.possibleModes.length == 2) {
98  newMode = currentMode; // there is no other mode available
99  break;
100  }
101  }
102  }
103 
104  changeLegModeTo(tour, newMode);
105  }
106  }
107 
108  private <T> boolean contains(T[] array, T value) {
109  for (T t : array) {
110  if (t.equals(value)) {
111  return true;
112  }
113  }
114  return false;
115  }
116 
117  private String getTransportMode(final List<PlanElement> tour) {
118  return ((Leg) (tour.get(1))).getMode();
119  }
120 
121  private void changeLegModeTo(final List<PlanElement> tour, final String newMode) {
122  for (PlanElement pe : tour) {
123  if (pe instanceof Leg) {
124  Leg leg = ((Leg) pe);
125  leg.setMode(newMode);
126  TripStructureUtils.setRoutingMode(leg, newMode);
127  Route route = leg.getRoute();
128  if (route instanceof NetworkRoute) {
129  ((NetworkRoute) route).setVehicleId(null);
130  }
131  }
132  }
133  }
134 
135  private int chooseModeOtherThan(final String currentMode) {
136  int newModeIdx = this.rng.nextInt(this.possibleModes.length - 1);
137  for (int i = 0; i <= newModeIdx; i++) {
138  if (this.possibleModes[i].equals(currentMode)) {
139  /* if the new Mode is after the currentMode in the list of possible
140  * modes, go one further, as we have to ignore the current mode in
141  * the list of possible modes. */
142  // This gives the mode after the current mode twice the weight. Not good. kai, feb'18
143  // No, it does not. It's good. We choose between 0 and possibleModes.length - 2
144  // (it's length - 1, but the upper bound of nextInt() is exclusive, thus it's essentially -2)
145  // This gives us exactly the number of possibilities of possibleModes with the current mode excluded.
146  // Instead of just accessing this.possibleModes[newModeIdx] we loop through the possible modes
147  // to figure out if currentMode is before or after the new mode. If it is before, we skip it
148  // by increasing the newModeIdx. In other words: If newModeIndex < currentModeIndex, we account for
149  // currentMode which we want to ignore by doing newModeIndex++. mrieser, feb'19
150  newModeIdx++;
151  break;
152  }
153  }
154  return newModeIdx;
155  }
156 
157 }
void setIgnoreCarAvailability(final boolean ignoreCarAvailability)
void changeToRandomLegMode(final List< PlanElement > tour, final Plan plan)
static String getCarAvail(Person person)
static void setRoutingMode(Leg leg, String mode)
void changeLegModeTo(final List< PlanElement > tour, final String newMode)
ChooseRandomLegMode(final String[] possibleModes, final Random rng, boolean allowSwitchFromListedModesOnly)
List< PlanElement > getPlanElements()