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