View Javadoc
1   package org.opentrafficsim.road.network.factory.xml.utils;
2   
3   import java.util.Map;
4   
5   import org.djunits.unit.AccelerationUnit;
6   import org.djunits.unit.DurationUnit;
7   import org.djunits.unit.FrequencyUnit;
8   import org.djunits.unit.LengthUnit;
9   import org.djunits.unit.LinearDensityUnit;
10  import org.djunits.unit.PositionUnit;
11  import org.djunits.unit.SpeedUnit;
12  import org.djunits.unit.TimeUnit;
13  import org.djunits.value.vdouble.scalar.Acceleration;
14  import org.djunits.value.vdouble.scalar.Duration;
15  import org.djunits.value.vdouble.scalar.Frequency;
16  import org.djunits.value.vdouble.scalar.Length;
17  import org.djunits.value.vdouble.scalar.LinearDensity;
18  import org.djunits.value.vdouble.scalar.Position;
19  import org.djunits.value.vdouble.scalar.Speed;
20  import org.djunits.value.vdouble.scalar.Time;
21  import org.opentrafficsim.core.units.distributions.ContinuousDistDoubleScalar;
22  import org.opentrafficsim.road.network.factory.xml.XmlParserException;
23  import org.opentrafficsim.xml.generated.ACCELERATIONDISTTYPE;
24  import org.opentrafficsim.xml.generated.CONTDISTTYPE;
25  import org.opentrafficsim.xml.generated.DISCRETEDISTTYPE;
26  import org.opentrafficsim.xml.generated.DURATIONDISTTYPE;
27  import org.opentrafficsim.xml.generated.FREQUENCYDISTTYPE;
28  import org.opentrafficsim.xml.generated.LENGTHDISTTYPE;
29  import org.opentrafficsim.xml.generated.LINEARDENSITYDISTTYPE;
30  import org.opentrafficsim.xml.generated.POSITIONDISTTYPE;
31  import org.opentrafficsim.xml.generated.SPEEDDISTTYPE;
32  import org.opentrafficsim.xml.generated.TIMEDISTTYPE;
33  
34  import nl.tudelft.simulation.jstats.distributions.DistBernoulli;
35  import nl.tudelft.simulation.jstats.distributions.DistBeta;
36  import nl.tudelft.simulation.jstats.distributions.DistBinomial;
37  import nl.tudelft.simulation.jstats.distributions.DistConstant;
38  import nl.tudelft.simulation.jstats.distributions.DistContinuous;
39  import nl.tudelft.simulation.jstats.distributions.DistDiscrete;
40  import nl.tudelft.simulation.jstats.distributions.DistDiscreteConstant;
41  import nl.tudelft.simulation.jstats.distributions.DistDiscreteUniform;
42  import nl.tudelft.simulation.jstats.distributions.DistErlang;
43  import nl.tudelft.simulation.jstats.distributions.DistExponential;
44  import nl.tudelft.simulation.jstats.distributions.DistGamma;
45  import nl.tudelft.simulation.jstats.distributions.DistGeometric;
46  import nl.tudelft.simulation.jstats.distributions.DistLogNormal;
47  import nl.tudelft.simulation.jstats.distributions.DistNegBinomial;
48  import nl.tudelft.simulation.jstats.distributions.DistNormal;
49  import nl.tudelft.simulation.jstats.distributions.DistPearson5;
50  import nl.tudelft.simulation.jstats.distributions.DistPearson6;
51  import nl.tudelft.simulation.jstats.distributions.DistPoisson;
52  import nl.tudelft.simulation.jstats.distributions.DistTriangular;
53  import nl.tudelft.simulation.jstats.distributions.DistUniform;
54  import nl.tudelft.simulation.jstats.distributions.DistWeibull;
55  import nl.tudelft.simulation.jstats.streams.StreamInterface;
56  
57  /**
58   * Parse a distribution from text to a distribution.
59   * <p>
60   * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
61   * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
62   * <p>
63   * $LastChangedDate: 2015-07-24 02:58:59 +0200 (Fri, 24 Jul 2015) $, @version $Revision: 1147 $, by $Author: averbraeck $,
64   * initial version Jul 23, 2015 <br>
65   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
66   */
67  public final class ParseDistribution
68  {
69      /** Utility class. */
70      private ParseDistribution() 
71      {
72          // do not instantiate
73      }
74  
75      /**
76       * Parse a discrete distribution.
77       * @param streamMap map with stream information
78       * @param distType the distribution to parse
79       * @return the generated distribution.
80       * @throws XmlParserException in case distribution unknown or parameter number does not match.
81       */
82      public static DistDiscrete makeDistDiscrete(final Map<String, StreamInformation> streamMap, final DISCRETEDISTTYPE distType)
83              throws XmlParserException
84      {
85          if (distType.getBERNOULLI() != null)
86          {
87              StreamInterface stream = findStream(streamMap, distType.getBERNOULLI().getRANDOMSTREAM());
88              return new DistBernoulli(stream, distType.getBERNOULLI().getP());
89          }
90          else if (distType.getBINOMIAL() != null)
91          {
92              StreamInterface stream = findStream(streamMap, distType.getBINOMIAL().getRANDOMSTREAM());
93              return new DistBinomial(stream, distType.getBINOMIAL().getN().longValue(), distType.getBINOMIAL().getP());
94          }
95          else if (distType.getCONSTANT() != null)
96          {
97              StreamInterface stream = findStream(streamMap, distType.getCONSTANT().getRANDOMSTREAM());
98              return new DistDiscreteConstant(stream, distType.getCONSTANT().getC());
99          }
100         else if (distType.getGEOMETRIC() != null)
101         {
102             StreamInterface stream = findStream(streamMap, distType.getGEOMETRIC().getRANDOMSTREAM());
103             return new DistGeometric(stream, distType.getGEOMETRIC().getP());
104         }
105         else if (distType.getNEGBINOMIAL() != null)
106         {
107             StreamInterface stream = findStream(streamMap, distType.getNEGBINOMIAL().getRANDOMSTREAM());
108             return new DistNegBinomial(stream, distType.getNEGBINOMIAL().getN().longValue(), distType.getGEOMETRIC().getP());
109         }
110         else if (distType.getPOISSON() != null)
111         {
112             StreamInterface stream = findStream(streamMap, distType.getPOISSON().getRANDOMSTREAM());
113             return new DistPoisson(stream, distType.getPOISSON().getLAMBDA());
114         }
115         else if (distType.getUNIFORM() != null)
116         {
117             StreamInterface stream = findStream(streamMap, distType.getUNIFORM().getRANDOMSTREAM());
118             return new DistDiscreteUniform(stream, distType.getUNIFORM().getMIN(), distType.getUNIFORM().getMAX());
119         }
120         throw new XmlParserException("makeDistDiscrete - unknown distribution function " + distType);
121     }
122 
123     /**
124      * Parse a continuous distribution.
125      * @param streamMap map with stream information
126      * @param distType the distribution to parse
127      * @return the generated distribution.
128      * @throws XmlParserException in case distribution unknown or parameter number does not match.
129      */
130     public static DistContinuous makeDistContinuous(final Map<String, StreamInformation> streamMap, final CONTDISTTYPE distType)
131             throws XmlParserException
132     {
133         if (distType.getCONSTANT() != null)
134         {
135             StreamInterface stream = findStream(streamMap, distType.getCONSTANT().getRANDOMSTREAM());
136             return new DistConstant(stream, distType.getCONSTANT().getC());
137         }
138         else if (distType.getEXPONENTIAL() != null)
139         {
140             StreamInterface stream = findStream(streamMap, distType.getEXPONENTIAL().getRANDOMSTREAM());
141             return new DistExponential(stream, distType.getEXPONENTIAL().getLAMBDA());
142         }
143         else if (distType.getTRIANGULAR() != null)
144         {
145             StreamInterface stream = findStream(streamMap, distType.getTRIANGULAR().getRANDOMSTREAM());
146             return new DistTriangular(stream, distType.getTRIANGULAR().getMIN(), distType.getTRIANGULAR().getMODE(),
147                     distType.getTRIANGULAR().getMAX());
148         }
149         else if (distType.getNORMAL() != null)
150         {
151             StreamInterface stream = findStream(streamMap, distType.getNORMAL().getRANDOMSTREAM());
152             return new DistNormal(stream, distType.getNORMAL().getMU(), distType.getNORMAL().getSIGMA());
153         }
154         // TODO: NORMALTRUNC
155         else if (distType.getBETA() != null)
156         {
157             StreamInterface stream = findStream(streamMap, distType.getBETA().getRANDOMSTREAM());
158             return new DistBeta(stream, distType.getBETA().getALPHA1(), distType.getBETA().getALPHA2());
159         }
160         else if (distType.getERLANG() != null)
161         {
162             StreamInterface stream = findStream(streamMap, distType.getERLANG().getRANDOMSTREAM());
163             return new DistErlang(stream, distType.getERLANG().getK().intValue(), distType.getERLANG().getMEAN());
164         }
165         else if (distType.getGAMMA() != null)
166         {
167             StreamInterface stream = findStream(streamMap, distType.getGAMMA().getRANDOMSTREAM());
168             return new DistGamma(stream, distType.getGAMMA().getALPHA(), distType.getGAMMA().getBETA());
169         }
170         else if (distType.getLOGNORMAL() != null)
171         {
172             StreamInterface stream = findStream(streamMap, distType.getLOGNORMAL().getRANDOMSTREAM());
173             return new DistLogNormal(stream, distType.getLOGNORMAL().getMU(), distType.getLOGNORMAL().getSIGMA());
174         }
175         else if (distType.getPEARSON5() != null)
176         {
177             StreamInterface stream = findStream(streamMap, distType.getPEARSON5().getRANDOMSTREAM());
178             return new DistPearson5(stream, distType.getPEARSON5().getALPHA(), distType.getPEARSON5().getBETA());
179         }
180         else if (distType.getPEARSON6() != null)
181         {
182             StreamInterface stream = findStream(streamMap, distType.getPEARSON6().getRANDOMSTREAM());
183             return new DistPearson6(stream, distType.getPEARSON6().getALPHA1(), distType.getPEARSON6().getALPHA2(),
184                     distType.getPEARSON6().getBETA());
185         }
186         else if (distType.getUNIFORM() != null)
187         {
188             StreamInterface stream = findStream(streamMap, distType.getUNIFORM().getRANDOMSTREAM());
189             return new DistUniform(stream, distType.getUNIFORM().getMIN(), distType.getUNIFORM().getMAX());
190         }
191         else if (distType.getWEIBULL() != null)
192         {
193             StreamInterface stream = findStream(streamMap, distType.getWEIBULL().getRANDOMSTREAM());
194             return new DistWeibull(stream, distType.getWEIBULL().getALPHA(), distType.getWEIBULL().getBETA());
195         }
196         throw new XmlParserException("makeDistContinuous - unknown distribution function " + distType);
197     }
198 
199     /**
200      * Find and return the stream belonging to te streamId.
201      * @param streamMap the map with streams from the RUN tag
202      * @param streamId the id to search for
203      * @return the stream belonging to te streamId
204      * @throws XmlParserException when the stream could not be found
205      */
206     private static StreamInterface findStream(final Map<String, StreamInformation> streamMap, final String streamId)
207             throws XmlParserException
208     {
209         StreamInformation streamInformation = streamMap.get(streamId);
210         if (streamInformation == null)
211         {
212             throw new XmlParserException("Could not find stream with ID=" + streamId);
213         }
214         return streamInformation.getStream();
215     }
216 
217     /**
218      * Parse a relative length distribution, e.g. <code>UNIFORM(1, 3) m</code>.
219      * @param streamMap the map with streams from the RUN tag
220      * @param lengthDist the tag to parse
221      * @return a typed continuous random distribution.
222      * @throws XmlParserException in case of a parse error.
223      */
224     public static ContinuousDistDoubleScalar.Rel<Length, LengthUnit> parseLengthDist(
225             final Map<String, StreamInformation> streamMap, final LENGTHDISTTYPE lengthDist) throws XmlParserException
226     {
227         DistContinuous dist = makeDistContinuous(streamMap, lengthDist);
228         for (LengthUnit unit : LengthUnit.BASE.getUnitsById().values())
229         {
230             if (unit.getAbbreviations().contains(lengthDist.getLENGTHUNIT()))
231             {
232                 return new ContinuousDistDoubleScalar.Rel<Length, LengthUnit>(dist, unit);
233             }
234         }
235         throw new XmlParserException(
236                 "Could not find LengthUnit " + lengthDist.getLENGTHUNIT() + " in tag of type LENGTHDISTTYPE");
237     }
238 
239     /**
240      * Parse an absolute position distribution, e.g. <code>UNIFORM(1, 3) m</code>.
241      * @param streamMap the map with streams from the RUN tag
242      * @param positionDist the tag to parse
243      * @return a typed continuous random distribution.
244      * @throws XmlParserException in case of a parse error.
245      */
246     public static ContinuousDistDoubleScalar.Abs<Position, PositionUnit, LengthUnit> parsePositionDist(
247             final Map<String, StreamInformation> streamMap, final POSITIONDISTTYPE positionDist) throws XmlParserException
248     {
249         DistContinuous dist = makeDistContinuous(streamMap, positionDist);
250         for (PositionUnit unit : PositionUnit.BASE.getUnitsById().values())
251         {
252             if (unit.getAbbreviations().contains(positionDist.getPOSITIONUNIT()))
253             {
254                 return new ContinuousDistDoubleScalar.Abs<Position, PositionUnit, LengthUnit>(dist, unit);
255             }
256         }
257         throw new XmlParserException(
258                 "Could not find PositionUnit " + positionDist.getPOSITIONUNIT() + " in tag of type POSITIONDISTTYPE");
259     }
260 
261     /**
262      * Parse a relative duration distribution, e.g. <code>UNIFORM(1, 3) s</code>.
263      * @param streamMap the map with streams from the RUN tag
264      * @param durationDist the tag to parse
265      * @return a typed continuous random distribution.
266      * @throws XmlParserException in case of a parse error.
267      */
268     public static ContinuousDistDoubleScalar.Rel<Duration, DurationUnit> parseDurationDist(
269             final Map<String, StreamInformation> streamMap, final DURATIONDISTTYPE durationDist) throws XmlParserException
270     {
271         DistContinuous dist = makeDistContinuous(streamMap, durationDist);
272         for (DurationUnit unit : DurationUnit.BASE.getUnitsById().values())
273         {
274             if (unit.getAbbreviations().contains(durationDist.getDURATIONUNIT()))
275             {
276                 return new ContinuousDistDoubleScalar.Rel<Duration, DurationUnit>(dist, unit);
277             }
278         }
279         throw new XmlParserException(
280                 "Could not find DurationUnit " + durationDist.getDURATIONUNIT() + " in tag of type DURATIONDISTTYPE");
281     }
282 
283     /**
284      * Parse an absolute time distribution, e.g. <code>UNIFORM(1, 3) s</code>.
285      * @param streamMap the map with streams from the RUN tag
286      * @param timeDist the tag to parse
287      * @return a typed continuous random distribution.
288      * @throws XmlParserException in case of a parse error.
289      */
290     public static ContinuousDistDoubleScalar.Abs<Time, TimeUnit, DurationUnit> parseTimeDist(
291             final Map<String, StreamInformation> streamMap, final TIMEDISTTYPE timeDist) throws XmlParserException
292     {
293         DistContinuous dist = makeDistContinuous(streamMap, timeDist);
294         for (TimeUnit unit : TimeUnit.BASE.getUnitsById().values())
295         {
296             if (unit.getAbbreviations().contains(timeDist.getTIMEUNIT()))
297             {
298                 return new ContinuousDistDoubleScalar.Abs<Time, TimeUnit, DurationUnit>(dist, unit);
299             }
300         }
301         throw new XmlParserException("Could not find TimeUnit " + timeDist.getTIMEUNIT() + " in tag of type TIMEDISTTYPE");
302     }
303 
304     /**
305      * Parse a relative speed distribution, e.g. <code>UNIFORM(1, 3) m/s</code>.
306      * @param streamMap the map with streams from the RUN tag
307      * @param speedDist the tag to parse
308      * @return a typed continuous random distribution.
309      * @throws XmlParserException in case of a parse error.
310      */
311     public static ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit> parseSpeedDist(
312             final Map<String, StreamInformation> streamMap, final SPEEDDISTTYPE speedDist) throws XmlParserException
313     {
314         DistContinuous dist = makeDistContinuous(streamMap, speedDist);
315         for (SpeedUnit unit : SpeedUnit.BASE.getUnitsById().values())
316         {
317             if (unit.getAbbreviations().contains(speedDist.getSPEEDUNIT()))
318             {
319                 return new ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit>(dist, unit);
320             }
321         }
322         throw new XmlParserException("Could not find SpeedUnit " + speedDist.getSPEEDUNIT() + " in tag of type SPEEDDISTTYPE");
323     }
324 
325     /**
326      * Parse a relative acceleration distribution, e.g. <code>UNIFORM(1, 3) s</code>.
327      * @param streamMap the map with streams from the RUN tag
328      * @param accelerationDist the tag to parse
329      * @return a typed continuous random distribution.
330      * @throws XmlParserException in case of a parse error.
331      */
332     public static ContinuousDistDoubleScalar.Rel<Acceleration, AccelerationUnit> parseAccelerationDist(
333             final Map<String, StreamInformation> streamMap, final ACCELERATIONDISTTYPE accelerationDist)
334             throws XmlParserException
335     {
336         DistContinuous dist = makeDistContinuous(streamMap, accelerationDist);
337         for (AccelerationUnit unit : AccelerationUnit.BASE.getUnitsById().values())
338         {
339             if (unit.getAbbreviations().contains(accelerationDist.getACCELERATIONUNIT()))
340             {
341                 return new ContinuousDistDoubleScalar.Rel<Acceleration, AccelerationUnit>(dist, unit);
342             }
343         }
344         throw new XmlParserException("Could not find AccelerationUnit " + accelerationDist.getACCELERATIONUNIT()
345                 + " in tag of type ACCELERATIONDISTTYPE");
346     }
347 
348     /**
349      * Parse a relative frequency distribution, e.g. <code>UNIFORM(1, 3) s</code>.
350      * @param streamMap the map with streams from the RUN tag
351      * @param frequencyDist the tag to parse
352      * @return a typed continuous random distribution.
353      * @throws XmlParserException in case of a parse error.
354      */
355     public static ContinuousDistDoubleScalar.Rel<Frequency, FrequencyUnit> parseFrequencyDist(
356             final Map<String, StreamInformation> streamMap, final FREQUENCYDISTTYPE frequencyDist) throws XmlParserException
357     {
358         DistContinuous dist = makeDistContinuous(streamMap, frequencyDist);
359         for (FrequencyUnit unit : FrequencyUnit.BASE.getUnitsById().values())
360         {
361             if (unit.getAbbreviations().contains(frequencyDist.getFREQUENCYUNIT()))
362             {
363                 return new ContinuousDistDoubleScalar.Rel<Frequency, FrequencyUnit>(dist, unit);
364             }
365         }
366         throw new XmlParserException(
367                 "Could not find FrequencyUnit " + frequencyDist.getFREQUENCYUNIT() + " in tag of type FREQUENCYDISTTYPE");
368     }
369 
370     /**
371      * Parse a relative linear density distribution, e.g. <code>UNIFORM(1, 3) s</code>.
372      * @param streamMap the map with streams from the RUN tag
373      * @param linearDensityDist the tag to parse
374      * @return a typed continuous random distribution.
375      * @throws XmlParserException in case of a parse error.
376      */
377     public static ContinuousDistDoubleScalar.Rel<LinearDensity, LinearDensityUnit> parseLinearDensityDist(
378             final Map<String, StreamInformation> streamMap, final LINEARDENSITYDISTTYPE linearDensityDist)
379             throws XmlParserException
380     {
381         DistContinuous dist = makeDistContinuous(streamMap, linearDensityDist);
382         for (LinearDensityUnit unit : LinearDensityUnit.BASE.getUnitsById().values())
383         {
384             if (unit.getAbbreviations().contains(linearDensityDist.getLINEARDENSITYUNIT()))
385             {
386                 return new ContinuousDistDoubleScalar.Rel<LinearDensity, LinearDensityUnit>(dist, unit);
387             }
388         }
389         throw new XmlParserException("Could not find FrequencyUnit " + linearDensityDist.getLINEARDENSITYUNIT()
390                 + " in tag of type FREQUENCYDISTTYPE");
391     }
392 
393 }