1 package org.opentrafficsim.road.od;
2
3 import java.util.LinkedHashMap;
4 import java.util.Map;
5
6 import org.djunits.value.vdouble.scalar.Frequency;
7 import org.djunits.value.vdouble.scalar.Length;
8 import org.djutils.exceptions.Throw;
9 import org.opentrafficsim.core.gtu.GtuErrorHandler;
10 import org.opentrafficsim.core.gtu.GtuType;
11 import org.opentrafficsim.core.idgenerator.IdGenerator;
12 import org.opentrafficsim.core.network.LinkType;
13 import org.opentrafficsim.core.network.Node;
14 import org.opentrafficsim.road.gtu.generator.CfBaRoomChecker;
15 import org.opentrafficsim.road.gtu.generator.GeneratorPositions.LaneBiases;
16 import org.opentrafficsim.road.gtu.generator.LaneBasedGtuGenerator.RoomChecker;
17 import org.opentrafficsim.road.gtu.generator.MarkovCorrelation;
18 import org.opentrafficsim.road.gtu.generator.characteristics.LaneBasedGtuCharacteristicsGeneratorOd;
19 import org.opentrafficsim.road.gtu.generator.headway.ArrivalsHeadwayGenerator.HeadwayDistribution;
20 import org.opentrafficsim.road.network.lane.Lane;
21
22 /**
23 * Options for vehicle generation based on an OD matrix.
24 * <p>
25 * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
26 * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
27 * </p>
28 * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
29 * @author <a href="https://github.com/peter-knoppers">Peter Knoppers</a>
30 * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
31 */
32 public class OdOptions
33 {
34 /** Headway randomization option. */
35 public static final Option<HeadwayDistribution> HEADWAY_DIST =
36 new Option<>("headway distribution", HeadwayDistribution.EXPONENTIAL);
37
38 /** ID generator option. */
39 public static final Option<IdGenerator> GTU_ID = new Option<>("gtu id", new IdGenerator(""));
40
41 /** GTU characteristics generator option. */
42 public static final Option<LaneBasedGtuCharacteristicsGeneratorOd> GTU_TYPE = new Option<>("gtu type", null);
43
44 /** Room checker option. */
45 public static final Option<RoomChecker> ROOM_CHECKER = new Option<>("room checker", new CfBaRoomChecker());
46
47 /** Markov chain for GTU type option. */
48 public static final Option<MarkovCorrelation<GtuType, Frequency>> MARKOV = new Option<>("markov", null);
49
50 /** Initial distance over which lane changes shouldn't be performed option. */
51 public static final Option<Length> NO_LC_DIST = new Option<>("no lc distance", null);
52
53 /** Whether to perform instantaneous lane changes. */
54 public static final Option<Boolean> INSTANT_LC = new Option<>("instant lc", false);
55
56 /** Error handler when GTU exceptions occur. */
57 public static final Option<GtuErrorHandler> ERROR_HANDLER = new Option<>("error handler", GtuErrorHandler.THROW);
58
59 /** Lane bias. Default is none, i.e. uniform distribution over lanes for all GTU types. */
60 public static final Option<LaneBiases> LANE_BIAS = new Option<>("lane bias", new LaneBiases());
61
62 /** Options overall. */
63 private OptionSet<Void> options = new OptionSet<>();
64
65 /** Options per lane. */
66 private OptionSet<Lane> laneOptions = new OptionSet<>();
67
68 /** Options per node. */
69 private OptionSet<Node> nodeOptions = new OptionSet<>();
70
71 /** Options per road type. */
72 private OptionSet<LinkType> linkTypeOptions = new OptionSet<>();
73
74 /**
75 * Set option value.
76 * @param option option
77 * @param value option value
78 * @param <K> value type
79 * @return this option set
80 */
81 public final <K> OdOptions set(final Option<K> option, final K value)
82 {
83 this.options.set(null, option, value);
84 return this;
85 }
86
87 /**
88 * Set option value for lane.
89 * @param lane lane
90 * @param option option
91 * @param value option value
92 * @param <K> value type
93 * @return this option set
94 */
95 public final <K> OdOptions set(final Lane lane, final Option<K> option, final K value)
96 {
97 this.laneOptions.set(lane, option, value);
98 return this;
99 }
100
101 /**
102 * Set option value for node.
103 * @param node node
104 * @param option option
105 * @param value option value
106 * @param <K> value type
107 * @return this option set
108 */
109 public final <K> OdOptions set(final Node node, final Option<K> option, final K value)
110 {
111 this.nodeOptions.set(node, option, value);
112 return this;
113 }
114
115 /**
116 * Set option value for link type.
117 * @param linkType link type
118 * @param option option
119 * @param value option value
120 * @param <K> value type
121 * @return this option set
122 */
123 public final <K> OdOptions set(final LinkType linkType, final Option<K> option, final K value)
124 {
125 this.linkTypeOptions.set(linkType, option, value);
126 return this;
127 }
128
129 /**
130 * Get option value. If a value is specified for a specific category, it is returned. The following order is used:
131 * <ul>
132 * <li>{@code Lane}</li>
133 * <li>{@code Node} (origin)</li>
134 * <li>{@code LinkType}</li>
135 * <li>None (global option value)</li>
136 * <li>Default option value</li>
137 * </ul>
138 * @param option option
139 * @param lane lane to obtain specific option value, may be null
140 * @param node node to obtain specific option value, may be null
141 * @param linkType link type to obtain specific option value, may be null
142 * @param <K> value type
143 * @return option value
144 */
145 public final <K> K get(final Option<K> option, final Lane lane, final Node node, final LinkType linkType)
146 {
147 Throw.whenNull(option, "Option may not be null.");
148 K value = this.laneOptions.get(lane, option);
149 if (value != null)
150 {
151 return value;
152 }
153 value = this.nodeOptions.get(node, option);
154 if (value != null)
155 {
156 return value;
157 }
158 value = this.linkTypeOptions.get(linkType, option);
159 if (value != null)
160 {
161 return value;
162 }
163 value = this.options.get(null, option);
164 if (value != null)
165 {
166 return value;
167 }
168 return option.getDefaultValue();
169 }
170
171 /**
172 * Utility class to store options.
173 * <p>
174 * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
175 * <br>
176 * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
177 * </p>
178 * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
179 * @author <a href="https://github.com/peter-knoppers">Peter Knoppers</a>
180 * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
181 * @param <K> option value type
182 */
183 public static final class Option<K>
184 {
185
186 /** Id. */
187 private final String id;
188
189 /** Default value. */
190 private final K defaultValue;
191
192 /**
193 * Constructor.
194 * @param id id
195 * @param defaultValue default value
196 */
197 Option(final String id, final K defaultValue)
198 {
199 this.id = id;
200 this.defaultValue = defaultValue;
201 }
202
203 /**
204 * Returns the default value.
205 * @return default value
206 */
207 public K getDefaultValue()
208 {
209 return this.defaultValue;
210 }
211
212 @Override
213 public int hashCode()
214 {
215 final int prime = 31;
216 int result = 1;
217 result = prime * result + ((this.id == null) ? 0 : this.id.hashCode());
218 return result;
219 }
220
221 @Override
222 public boolean equals(final Object obj)
223 {
224 if (this == obj)
225 {
226 return true;
227 }
228 if (obj == null)
229 {
230 return false;
231 }
232 if (getClass() != obj.getClass())
233 {
234 return false;
235 }
236 Option<?> other = (Option<?>) obj;
237 if (this.id == null)
238 {
239 if (other.id != null)
240 {
241 return false;
242 }
243 }
244 else if (!this.id.equals(other.id))
245 {
246 return false;
247 }
248 return true;
249 }
250
251 @Override
252 public String toString()
253 {
254 return "Option [id=" + this.id + "]";
255 }
256
257 }
258
259 /**
260 * Single set of options for a certain category, i.e. lane, node, link type or null (i.e. global).
261 * <p>
262 * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
263 * <br>
264 * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
265 * </p>
266 * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
267 * @author <a href="https://github.com/peter-knoppers">Peter Knoppers</a>
268 * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
269 * @param <C> category type, i.e. {@code Lane}, {@code Node}, {@code LinkType} or {@code Void} (i.e. global).
270 */
271 private class OptionSet<C>
272 {
273
274 /** Options. */
275 private Map<C, Map<Option<?>, Object>> optionsSet = new LinkedHashMap<>();
276
277 /**
278 * Constructor.
279 */
280 OptionSet()
281 {
282 //
283 }
284
285 /**
286 * Set value in option set.
287 * @param category category
288 * @param option option
289 * @param value value
290 * @param <K> option value type
291 */
292 public <K> void set(final C category, final Option<K> option, final K value)
293 {
294 Map<Option<?>, Object> map = this.optionsSet.get(category);
295 if (map == null)
296 {
297 map = new LinkedHashMap<>();
298 this.optionsSet.put(category, map);
299 }
300 map.put(option, value);
301 }
302
303 /**
304 * Returns the option value for the category.
305 * @param category category
306 * @param option option
307 * @return option value for the category
308 * @param <K> value type
309 */
310 @SuppressWarnings("unchecked")
311 public <K> K get(final C category, final Option<K> option)
312 {
313 if (!this.optionsSet.containsKey(category))
314 {
315 return null;
316 }
317 return (K) this.optionsSet.get(category).get(option);
318 }
319
320 }
321
322 }