1 | package de.uka.ipd.sdq.statistics; |
2 | |
3 | import java.util.ArrayList; |
4 | |
5 | /** |
6 | * Implements the "Crossing the mean" heuristic for filtering the warm-up period |
7 | * of a steady state simulation. The warm-up period will rather be underestimated. |
8 | * <p> |
9 | * Please note that there is no common interface for warm-up filters so far! |
10 | * Thus the interface will likely change soon. |
11 | * |
12 | * @author Philipp Merkle |
13 | * |
14 | */ |
15 | public class CrossingMeanWarmUpFilter { |
16 | |
17 | /** |
18 | * determines how often the mean have to be crossed until subsequent samples |
19 | * are considered to be stationary |
20 | */ |
21 | private static final int MEAN_CROSSINGS_STATIONARY = 5; |
22 | |
23 | private ArrayList<Double> buffer; |
24 | |
25 | /** sum of buffered samples. Enables efficient mean calculation */ |
26 | private double samplesSum; |
27 | |
28 | public CrossingMeanWarmUpFilter() { |
29 | buffer = new ArrayList<Double>(); |
30 | } |
31 | |
32 | public void offerSample(Double sample) { |
33 | buffer.add(sample); |
34 | samplesSum += sample; |
35 | } |
36 | |
37 | public boolean isStationary() { |
38 | return computeMeanCrossings(computeCurrentMean()) >= MEAN_CROSSINGS_STATIONARY; |
39 | } |
40 | |
41 | private int computeMeanCrossings(double mean) { |
42 | int crossings = 0; |
43 | Double prevSample = null; |
44 | for (Double currSample : buffer) { |
45 | if (prevSample == null) { |
46 | prevSample = currSample; |
47 | continue; |
48 | } |
49 | |
50 | if (prevSample < currSample) { |
51 | if (prevSample < mean && currSample > mean) { |
52 | ++crossings; |
53 | } |
54 | } else { |
55 | if (prevSample > mean && currSample < mean) { |
56 | ++crossings; |
57 | } |
58 | } |
59 | |
60 | prevSample = currSample; |
61 | } |
62 | return crossings; |
63 | } |
64 | |
65 | private double computeCurrentMean() { |
66 | return samplesSum / buffer.size(); |
67 | } |
68 | |
69 | } |