1 package org.opentrafficsim.core.gtu.behavioralcharacteristics;
2
3 import java.io.Serializable;
4 import java.util.HashMap;
5 import java.util.Iterator;
6 import java.util.LinkedHashMap;
7 import java.util.LinkedHashSet;
8 import java.util.Map;
9 import java.util.Set;
10
11 import org.djunits.unit.Unit;
12 import org.djunits.value.vdouble.scalar.AbstractDoubleScalarRel;
13 import org.djunits.value.vdouble.scalar.DoubleScalarInterface;
14 import org.opentrafficsim.base.parameters.ParameterException;
15 import org.opentrafficsim.base.parameters.ParameterType;
16 import org.opentrafficsim.base.parameters.ParameterTypeDouble;
17 import org.opentrafficsim.base.parameters.ParameterTypeNumeric;
18 import org.opentrafficsim.base.parameters.Parameters;
19 import org.opentrafficsim.core.gtu.GTUType;
20 import org.opentrafficsim.core.units.distributions.ContinuousDistDoubleScalar;
21
22 import nl.tudelft.simulation.jstats.distributions.DistContinuous;
23
24
25
26
27
28
29
30
31
32
33
34
35
36 public class ParameterFactoryByType implements ParameterFactory
37 {
38
39
40 private final Map<GTUType, Set<ParameterEntry<?>>> map = new HashMap<>();
41
42
43 private Map<GTUType, Map<ParameterType<?>, Map<ParameterType<?>, Correlation<?, ?>>>> correlations = new HashMap<>();
44
45
46 @Override
47 public void setValues(final Parameters parameters, final GTUType gtuType)
48 {
49
50 Map<ParameterType<?>, ParameterEntry<?>> setType = new LinkedHashMap<>();
51 for (GTUType type : new GTUType[] { null, gtuType })
52 {
53 if (this.map.containsKey(type))
54 {
55 for (ParameterEntry<?> entry : this.map.get(type))
56 {
57 setType.put(entry.getParameterType(), entry);
58 }
59 }
60 }
61
62
63
64
65
66
67
68
69
70
71
72 Map<ParameterType<?>, Map<ParameterType<?>, Correlation<?, ?>>> remainingCorrelations = new LinkedHashMap<>();
73 Map<ParameterType<?>, Map<ParameterType<?>, Correlation<?, ?>>> allCorrelations = new LinkedHashMap<>();
74 for (GTUType type : new GTUType[] { null, gtuType })
75 {
76 if (this.correlations.containsKey(type))
77 {
78 Map<ParameterType<?>, Map<ParameterType<?>, Correlation<?, ?>>> map1 = this.correlations.get(type);
79 for (ParameterType<?> then : map1.keySet())
80 {
81 Map<ParameterType<?>, Correlation<?, ?>> map2a = map1.get(then);
82 Map<ParameterType<?>, Correlation<?, ?>> map2b = new LinkedHashMap<>(map2a);
83
84 map2b.keySet().retainAll(setType.keySet());
85 if (!map2b.isEmpty())
86 {
87 Map<ParameterType<?>, Correlation<?, ?>> map3 = remainingCorrelations.get(then);
88 if (map3 == null)
89 {
90 map3 = new LinkedHashMap<>();
91 remainingCorrelations.put(then, map3);
92 }
93 map3.putAll(map2b);
94 }
95 if (!map2a.isEmpty())
96 {
97 Map<ParameterType<?>, Correlation<?, ?>> map3 = allCorrelations.get(then);
98 if (map3 == null)
99 {
100 map3 = new LinkedHashMap<>();
101 allCorrelations.put(then, map3);
102 }
103 map3.putAll(map2a);
104 }
105 }
106 }
107 }
108
109
110 boolean altered = true;
111 while (altered)
112 {
113 altered = false;
114
115 Iterator<ParameterType<?>> iterator = setType.keySet().iterator();
116 while (iterator.hasNext())
117 {
118 ParameterType<?> parameterType = iterator.next();
119 ParameterEntry<?> entry = setType.get(parameterType);
120
121 if (!remainingCorrelations.containsKey(parameterType))
122 {
123 altered = true;
124 iterator.remove();
125 Object value = entry.getValue();
126 setParameter(parameterType, value, parameters, allCorrelations.get(parameterType));
127
128 Iterator<ParameterType<?>> it = remainingCorrelations.keySet().iterator();
129 while (it.hasNext())
130 {
131 Map<ParameterType<?>, Correlation<?, ?>> remMap = remainingCorrelations.get(it.next());
132 remMap.remove(parameterType);
133 if (remMap.isEmpty())
134 {
135 it.remove();
136 }
137 }
138 }
139 }
140 }
141 if (!altered && !remainingCorrelations.isEmpty())
142 {
143 throw new RuntimeException("Circular correlation between parameters.");
144 }
145
146 }
147
148
149
150
151
152
153
154
155
156
157 @SuppressWarnings("unchecked")
158 private <C, T> void setParameter(final ParameterType<?> parameterType, final Object value, final Parameters parameters,
159 final Map<ParameterType<?>, Correlation<?, ?>> correls)
160 {
161 T val = (T) value;
162 try
163 {
164 if (correls != null)
165 {
166 for (ParameterType<?> param : correls.keySet())
167 {
168 Correlation<C, T> correlation = (Correlation<C, T>) correls.get(param);
169 if (param == null)
170 {
171 val = correlation.correlate(null, val);
172 }
173 else
174 {
175 val = correlation.correlate(parameters.getParameter((ParameterType<C>) param), val);
176 }
177 }
178 }
179 parameters.setParameter((ParameterType<T>) parameterType, val);
180 }
181 catch (ParameterException exception)
182 {
183 throw new RuntimeException("Value out of bounds or dependent parameter not present.", exception);
184 }
185 }
186
187
188
189
190
191
192
193 public <T extends DoubleScalarInterface> void addParameter(final GTUType gtuType, final ParameterType<T> parameterType,
194 final T value)
195 {
196 assureTypeInMap(gtuType);
197 this.map.get(gtuType).add(new FixedEntry<>(parameterType, value));
198 }
199
200
201
202
203
204
205 public void addParameter(final GTUType gtuType, final ParameterTypeDouble parameterType, final double value)
206 {
207 assureTypeInMap(gtuType);
208 this.map.get(gtuType).add(new FixedEntryDouble(parameterType, value));
209 }
210
211
212
213
214
215
216
217
218 public <U extends Unit<U>, T extends AbstractDoubleScalarRel<U, T>> void addParameter(final GTUType gtuType,
219 final ParameterTypeNumeric<T> parameterType, final ContinuousDistDoubleScalar.Rel<T, U> distribution)
220 {
221 assureTypeInMap(gtuType);
222 this.map.get(gtuType).add(new DistributedEntry<>(parameterType, distribution));
223 }
224
225
226
227
228
229
230 public void addParameter(final GTUType gtuType, final ParameterTypeDouble parameterType, final DistContinuous distribution)
231 {
232 assureTypeInMap(gtuType);
233 this.map.get(gtuType).add(new DistributedEntryDouble(parameterType, distribution));
234 }
235
236
237
238
239
240
241
242 public <T extends DoubleScalarInterface> void addParameter(final ParameterType<T> parameterType, final T value)
243 {
244 addParameter(null, parameterType, value);
245 }
246
247
248
249
250
251
252 public void addParameter(final ParameterTypeDouble parameterType, final double value)
253 {
254 addParameter(null, parameterType, value);
255 }
256
257
258
259
260
261
262
263
264 public <U extends Unit<U>, T extends AbstractDoubleScalarRel<U, T>> void addParameter(
265 final ParameterTypeNumeric<T> parameterType, final ContinuousDistDoubleScalar.Rel<T, U> distribution)
266 {
267 addParameter(null, parameterType, distribution);
268 }
269
270
271
272
273
274
275 public void addParameter(final ParameterTypeDouble parameterType, final DistContinuous distribution)
276 {
277 addParameter(null, parameterType, distribution);
278 }
279
280
281
282
283
284
285
286
287
288
289
290 public <C, T> void addCorrelation(final GTUType gtuType, final ParameterType<C> first, final ParameterType<T> then,
291 final Correlation<C, T> correlation)
292 {
293 assureTypeInMap(gtuType);
294 Map<ParameterType<?>, Map<ParameterType<?>, Correlation<?, ?>>> map1 = this.correlations.get(gtuType);
295 Map<ParameterType<?>, Correlation<?, ?>> map2 = map1.get(then);
296 if (map2 == null)
297 {
298 map2 = new LinkedHashMap<>();
299 map1.put(then, map2);
300 }
301 map2.put(first, correlation);
302 }
303
304
305
306
307
308
309
310
311
312 public <C, T> void addCorrelation(final ParameterType<C> first, final ParameterType<T> then,
313 final Correlation<C, T> correlation)
314 {
315 addCorrelation(null, first, then, correlation);
316 }
317
318
319
320
321
322 private void assureTypeInMap(final GTUType gtuType)
323 {
324 if (!this.map.containsKey(gtuType))
325 {
326 this.map.put(gtuType, new LinkedHashSet<>());
327 this.correlations.put(gtuType, new LinkedHashMap<>());
328 }
329 }
330
331
332 @Override
333 public String toString()
334 {
335 return "ParameterFactoryByType [map=" + this.map + "]";
336 }
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351 private interface ParameterEntry<T>
352 {
353
354
355
356
357 T getValue();
358
359
360
361
362
363 ParameterType<T> getParameterType();
364 }
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379 private final class FixedEntry<T> implements ParameterEntry<T>, Serializable
380 {
381
382 private static final long serialVersionUID = 20170400L;
383
384
385 private final ParameterType<T> parameterType;
386
387
388 private final T value;
389
390
391
392
393
394 FixedEntry(final ParameterType<T> parameterType, final T value)
395 {
396 this.parameterType = parameterType;
397 this.value = value;
398 }
399
400
401 @Override
402 public T getValue()
403 {
404 return this.value;
405 }
406
407
408 @Override
409 public ParameterType<T> getParameterType()
410 {
411 return this.parameterType;
412 }
413
414
415 @Override
416 public String toString()
417 {
418 return "FixedEntry [parameterType=" + this.parameterType + ", value=" + this.value + "]";
419 }
420
421 }
422
423
424
425
426
427
428
429
430
431
432
433
434
435 private final class FixedEntryDouble implements ParameterEntry<Double>, Serializable
436 {
437
438 private static final long serialVersionUID = 20170400L;
439
440
441 private final ParameterTypeDouble parameterType;
442
443
444 private final double value;
445
446
447
448
449
450 FixedEntryDouble(final ParameterTypeDouble parameterType, final double value)
451 {
452 this.parameterType = parameterType;
453 this.value = value;
454 }
455
456
457 @Override
458 public Double getValue()
459 {
460 return this.value;
461 }
462
463
464 @Override
465 public ParameterType<Double> getParameterType()
466 {
467 return this.parameterType;
468 }
469
470
471 @Override
472 public String toString()
473 {
474 return "FixedEntryDouble [parameterType=" + this.parameterType + ", value=" + this.value + "]";
475 }
476 }
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492 private final class DistributedEntry<U extends Unit<U>, T extends AbstractDoubleScalarRel<U, T>>
493 implements ParameterEntry<T>, Serializable
494 {
495
496 private static final long serialVersionUID = 20180203L;
497
498
499 private final ParameterType<T> parameterType;
500
501
502 private final ContinuousDistDoubleScalar.Rel<T, U> distribution;
503
504
505
506
507
508 DistributedEntry(final ParameterType<T> parameterType, final ContinuousDistDoubleScalar.Rel<T, U> distribution)
509 {
510 this.parameterType = parameterType;
511 this.distribution = distribution;
512 }
513
514
515 @Override
516 public T getValue()
517 {
518 return this.distribution.draw();
519 }
520
521
522 @Override
523 public ParameterType<T> getParameterType()
524 {
525 return this.parameterType;
526 }
527
528
529 @Override
530 public String toString()
531 {
532 return "DistributedEntry [parameterType=" + this.parameterType + ", distribution=" + this.distribution + "]";
533 }
534 }
535
536
537
538
539
540
541
542
543
544
545
546
547
548 private final class DistributedEntryDouble implements ParameterEntry<Double>, Serializable
549 {
550
551 private static final long serialVersionUID = 20180203L;
552
553
554 private final ParameterTypeDouble parameterType;
555
556
557 private final DistContinuous distribution;
558
559
560
561
562
563 DistributedEntryDouble(final ParameterTypeDouble parameterType, final DistContinuous distribution)
564 {
565 this.parameterType = parameterType;
566 this.distribution = distribution;
567 }
568
569
570 @Override
571 public Double getValue()
572 {
573 return this.distribution.draw();
574 }
575
576
577 @Override
578 public ParameterType<Double> getParameterType()
579 {
580 return this.parameterType;
581 }
582
583
584 @Override
585 public String toString()
586 {
587 return "DistributedEntryDouble [parameterType=" + this.parameterType + ", distribution=" + this.distribution + "]";
588 }
589 }
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605 @FunctionalInterface
606 public interface Correlation<C, T>
607 {
608
609
610
611
612
613
614 T correlate(C first, T then);
615 }
616
617 }