View Javadoc

1   /*
2    * @(#)Persistent.java Apr 3, 2003
3    * 
4    * Copyright (c) 2003 Delft University of Technology Jaffalaan 5, 2628 BX Delft,
5    * the Netherlands All rights reserved.
6    * 
7    * This software is proprietary information of Delft University of Technology
8    * The code is published under the General Public License
9    */
10  package nl.tudelft.simulation.jstats.statistics;
11  
12  import nl.tudelft.simulation.event.EventInterface;
13  import nl.tudelft.simulation.event.EventType;
14  import nl.tudelft.simulation.event.TimedEvent;
15  import nl.tudelft.simulation.logger.Logger;
16  
17  /***
18   * The Persisten class defines a statistics event persistent. A Persistent is a
19   * time-averaged tally.
20   * <p>
21   * (c) copyright 2003-2004 <a href="http://www.simulation.tudelft.nl">Delft
22   * University of Technology </a>, the Netherlands. <br>
23   * See for project information <a
24   * href="http://www.simulation.tudelft.nl">www.simulation.tudelft.nl </a> <br>
25   * License of use: <a href="http://www.gnu.org/copyleft/gpl.html">General Public
26   * License (GPL) </a>, no warranty <br>
27   * 
28   * @author <a href="http://www.simulation.tudelft.nl/people/jacobs.html">Peter
29   *         Jacobs </a>
30   * @version 1.15, 2004-03-23
31   * @since 1.2
32   */
33  public class Persistent extends Tally
34  {
35  	/*** VALUE_EVENT is fired whenever on a change in measurements */
36  	public static final EventType VALUE_EVENT = new EventType("VALUE_EVENT");
37  
38  	/*** startTime defines the time of the first event */
39  	private double startTime = Double.NaN;
40  
41  	/*** elapsedTime tracks the elapsed time */
42  	private double elapsedTime = Double.NaN;
43  
44  	/*** deltaTime defines the time between 2 events */
45  	private double deltaTime = Double.NaN;
46  
47  	/*** lastvalue tracks the last value */
48  	private double lastValue = Double.NaN;
49  
50  	/***
51  	 * constructs a new Persistent with a description.
52  	 * 
53  	 * @param description the description of this Persistent
54  	 */
55  	public Persistent(final String description)
56  	{
57  		super(description);
58  	}
59  
60  	/***
61  	 * @see nl.tudelft.simulation.jstats.statistics.Tally#getStdDev()
62  	 */
63  	public double getStdDev()
64  	{
65  		synchronized (this.semaphore)
66  		{
67  			if (super.n > 1)
68  			{
69  				return Math.sqrt(super.varianceSum
70  						/ (this.elapsedTime - this.deltaTime));
71  			}
72  			return Double.NaN;
73  		}
74  	}
75  
76  	/***
77  	 * @see nl.tudelft.simulation.jstats.statistics.Tally#getSampleVariance()
78  	 */
79  	public double getSampleVariance()
80  	{
81  		synchronized (this.semaphore)
82  		{
83  			if (super.n > 1)
84  			{
85  				return super.varianceSum / (this.elapsedTime - this.deltaTime);
86  			}
87  			return Double.NaN;
88  		}
89  	}
90  
91  	/***
92  	 * @see nl.tudelft.simulation.jstats.statistics.Tally#initialize()
93  	 */
94  	public void initialize()
95  	{
96  		synchronized (this.semaphore)
97  		{
98  			super.initialize();
99  			this.deltaTime = 0.0;
100 			this.elapsedTime = 0.0;
101 			this.lastValue = 0.0;
102 		}
103 	}
104 
105 	/***
106 	 * @see nl.tudelft.simulation.jstats.statistics.Tally
107 	 *      #notify(nl.tudelft.simulation.event.EventInterface)
108 	 */
109 	public void notify(final EventInterface event)
110 	{
111 		if (!(event instanceof TimedEvent)
112 				|| !(event.getContent() instanceof Number))
113 		{
114 			throw new IllegalArgumentException(
115 					"event !=TimedEvent || event.source !=Double ("
116 							+ event.getContent().getClass().toString() + ")");
117 		}
118 		TimedEvent timedEvent = (TimedEvent) event;
119 		double value = 0.0;
120 		if (event.getContent() instanceof Number)
121 		{
122 			value = ((Number) event.getContent()).doubleValue();
123 		} else
124 		{
125 			Logger.warning(this, "notify", event.getContent()
126 					+ "should be a number.");
127 		}
128 		synchronized (this.semaphore)
129 		{
130 			super.fireEvent(Persistent.VALUE_EVENT, this.lastValue, timedEvent
131 					.getTimeStamp());
132 			super.fireEvent(Persistent.VALUE_EVENT, value, timedEvent
133 					.getTimeStamp());
134 			super.setN(super.n + 1); //we increase the number of
135 			// measurements.
136 			if (value < super.min)
137 			{
138 				super.setMin(value);
139 			}
140 			if (value > super.max)
141 			{
142 				super.setMax(value);
143 			}
144 			super.setSum(super.sum + value);
145 
146 			//see Knuth's The Art Of Computer Programming Volume II:
147 			// Seminumerical Algorithms
148 			if (this.n == 1)
149 			{
150 				super.setSampleMean(value);
151 				this.startTime = timedEvent.getTimeStamp();
152 			} else
153 			{
154 				this.deltaTime = timedEvent.getTimeStamp()
155 						- (this.elapsedTime + this.startTime);
156 				if (this.deltaTime > 0.0)
157 				{
158 					double newAverage = ((super.sampleMean * (this.elapsedTime)) + (this.lastValue * this.deltaTime))
159 							/ (this.elapsedTime + this.deltaTime);
160 					super.varianceSum += (this.lastValue - super.sampleMean)
161 							* (this.lastValue - newAverage) * this.deltaTime;
162 					super.setSampleMean(newAverage);
163 					this.elapsedTime = this.elapsedTime + this.deltaTime;
164 				}
165 			}
166 			if (this.n > 1)
167 			{
168 				super.fireEvent(Tally.STANDARD_DEVIATION_EVENT, this
169 						.getStdDev());
170 				this.fireEvent(Tally.SAMPLE_VARIANCE_EVENT, this
171 						.getSampleVariance());
172 			}
173 			this.lastValue = value;
174 		}
175 	}
176 }