MATSIM
FixedIntervalTimeVariantAttribute.java
Go to the documentation of this file.
1 /* *********************************************************************** *
2  * project: org.matsim.*
3  * *
4  * *********************************************************************** *
5  * *
6  * copyright : (C) 2015 by the members listed in the COPYING, *
7  * LICENSE and WARRANTY file. *
8  * email : info at matsim dot org *
9  * *
10  * *********************************************************************** *
11  * *
12  * This program is free software; you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation; either version 2 of the License, or *
15  * (at your option) any later version. *
16  * See also COPYING, LICENSE and WARRANTY file *
17  * *
18  * *********************************************************************** */
19 
20 package org.matsim.core.network;
21 
22 import java.util.Arrays;
23 import java.util.TreeMap;
24 
28 
29 import com.google.common.base.Preconditions;
30 
35 final class FixedIntervalTimeVariantAttribute implements TimeVariantAttribute {
36  private final int timeSlice;
37  private final int numSlots;
38 
39  private double baseValue;
40  private double[] values;
41 
42  private int eventsCount = 0;
43  private int eventsCountWhenLastRecalc = -1;
44 
45  public FixedIntervalTimeVariantAttribute(int timeSlice, int maxTime) {
46  this.timeSlice = timeSlice;
47  this.numSlots = TimeBinUtils.getTimeBinCount(maxTime, timeSlice);
48  }
49 
50  @Override
51  public boolean isRecalcRequired() {
52  return eventsCountWhenLastRecalc != eventsCount;
53  }
54 
55  //TODO before calling this method we could convert changeEvents into a sequence of non-null changeValues
56  @Override
57  public void recalc(TreeMap<Double, NetworkChangeEvent> changeEvents, ChangeValueGetter valueGetter,
58  double baseValue1) {
59  this.baseValue = baseValue1;
60 
61  if (eventsCount == 0) {
62  return;
63  }
64 
65  //To save memory, the array is constructed only if there is at least one ChangeEvent.
66  //This saves a lot of memory in cases when only one attribute is time variant, while
67  //the remaining two are invariant.
68  if (values == null) {
69  values = new double[numSlots];
70  }
71 
72  int numEvent = 0;
73  int fromBin = 0;//inclusive
74  double currentValue = baseValue1;
75  if (changeEvents != null) {
76  for (NetworkChangeEvent event : changeEvents.values()) {
77  ChangeValue value = valueGetter.getChangeValue(event);
78  if (value != null) {
79  numEvent++;
80 
81  Preconditions.checkArgument(event.getStartTime() >= 0,
82  "The current implementation supports only non-negative change event times");
83  int toBin = (int)(event.getStartTime() / timeSlice);//exclusive
84  Arrays.fill(values, fromBin, toBin, currentValue);
85 
86  switch (value.getType()) {
87  case ABSOLUTE_IN_SI_UNITS:
88  currentValue = value.getValue();
89  break;
90  case FACTOR:
91  currentValue *= value.getValue();
92  break;
93  case OFFSET_IN_SI_UNITS:
94  currentValue += value.getValue();
95  break;
96  default:
97  throw new RuntimeException("unknown ChangeType");
98  }
99  fromBin = toBin;
100  }
101  }
102  }
103  Arrays.fill(values, fromBin, values.length, currentValue);
104  eventsCountWhenLastRecalc = eventsCount;
105 
106  if (numEvent != this.eventsCount) {
107  throw new RuntimeException("Expected number of change events ("
108  + (this.eventsCount)
109  + ") differs from the number of events found ("
110  + numEvent
111  + ")!");
112  }
113  }
114 
115  @Override
116  public double getValue(final double time) {
117  Preconditions.checkArgument(!Double.isNaN(time), "NaN time is not supported");
118  if (eventsCount == 0) {
119  return baseValue;
120  }
121 
122  int bin = TimeBinUtils.getTimeBinIndex(time, timeSlice, numSlots);
123  return bin < 0 ? baseValue : values[bin];
124  }
125 
126  @Override
127  public void incChangeEvents() {
128  eventsCount++;
129  }
130 
131  @Override
132  public void clearEvents() {
133  eventsCount = 0;
134  eventsCountWhenLastRecalc = -1;
135  values = null;
136  }
137 }