source: trunk/EventBenchCore/src/de/ugoe/cs/eventbench/coverage/CoverageCalculator.java @ 114

Last change on this file since 114 was 114, checked in by sherbold, 13 years ago
  • Property svn:mime-type set to text/plain
File size: 7.1 KB
Line 
1package de.ugoe.cs.eventbench.coverage;
2
3import java.security.InvalidParameterException;
4import java.util.Collection;
5import java.util.LinkedHashMap;
6import java.util.LinkedHashSet;
7import java.util.LinkedList;
8import java.util.List;
9import java.util.Map;
10import java.util.Set;
11
12import de.ugoe.cs.eventbench.data.Event;
13import de.ugoe.cs.eventbench.models.IStochasticProcess;
14
15/**
16 * <p>
17 * This class calculates various types of sequence coverage.
18 * </p>
19 *
20 * @author Steffen Herbold
21 * @version 1.0
22 */
23public class CoverageCalculator {
24
25        /**
26         * <p>
27         * Stochastic process that is the foundation for probabilistic coverages and
28         * coverages with reference to all possible sequences.
29         * </p>
30         */
31        private final IStochasticProcess process;
32
33        /**
34         * <p>
35         * Sequences for which the coverage is calculated.
36         * </p>
37         */
38        private final Collection<List<? extends Event<?>>> sequences;
39
40        /**
41         * <p>
42         * Length of the subsequences in relation to which the covarage is
43         * calculated.
44         * </p>
45         */
46        private final int length;
47
48        /**
49         * <p>
50         * All subsequences of {@link #length} of {@link #sequences}.
51         * </p>
52         */
53        private Collection<List<? extends Event<?>>> containedSubSeqs = null;
54
55        /**
56         * <p>
57         * All subsequences of {@link #length} that can be generated by
58         * {@link #process}.
59         * </p>
60         */
61        private Collection<List<? extends Event<?>>> allPossibleSubSeqs = null;
62
63        /**
64         * <p>
65         * The probabilities of al subsequences of {@link #length} according to
66         * {@link #process}.
67         * </p>
68         */
69        private Map<List<? extends Event<?>>, Double> subSeqWeights = null;
70
71        /**
72         * <p>
73         * Constructor. Creates a new CoverageCalculator for a given stochastic
74         * process and generated sequences.
75         * </p>
76         *
77         * @param process
78         *            stochastic process used for coverage calculations; must not be null
79         * @param sequences
80         *            sequences for which the coverage is calculated; must not be
81         *            null
82         * @param length
83         *            length of the subsequences for which the coverage is analyzed;
84         *            must be >0
85         */
86        public CoverageCalculator(IStochasticProcess process,
87                        Collection<List<? extends Event<?>>> sequences, int length) {
88                if( process==null ) {
89                        throw new InvalidParameterException("process must not be null");
90                }
91                if( sequences==null ) {
92                        throw new InvalidParameterException("sequences must not be null");
93                }
94                if( length<=0 ) {
95                        throw new InvalidParameterException("length must be >0; actual value: " + length);
96                }
97                this.process = process;
98                this.sequences = sequences;
99                this.length = length;
100        }
101
102        /**
103         * <p>
104         * Calculates the percentage of subsequences of length k that exist occur,
105         * including those that cannot be generated by {@link #process}.
106         * </p>
107         *
108         * @return coverage percentage
109         */
110        public double getCoverageAllNoWeight() {
111                if (containedSubSeqs == null) {
112                        containedSubSeqs = containedSubSequences(sequences, length);
113                }
114                return ((double) containedSubSeqs.size())
115                                / numSequences(process, length);
116        }
117
118        /**
119         * <p>
120         * Calculates the percentage of subsequences of length k that occur and can
121         * generated by {@link #process}.
122         * </p>
123         *
124         * @return coverage percentage
125         */
126        public double getCoveragePossibleNoWeight() {
127                if (containedSubSeqs == null) {
128                        containedSubSeqs = containedSubSequences(sequences, length);
129                }
130                if (allPossibleSubSeqs == null) {
131                        allPossibleSubSeqs = process.generateSequences(length);
132                }
133                return ((double) containedSubSeqs.size()) / allPossibleSubSeqs.size();
134        }
135
136        /**
137         * <p>
138         * Calculates the weight of the subsequences that occur with relation to
139         * {@link #process}, i.e., the mass of the subsequence probability covered
140         * by the subsequences.
141         * </p>
142         *
143         * @return coverage weight
144         */
145        public double getCoveragePossibleWeight() {
146                if (containedSubSeqs == null) {
147                        containedSubSeqs = containedSubSequences(sequences, length);
148                }
149                if (allPossibleSubSeqs == null) {
150                        allPossibleSubSeqs = process.generateSequences(length);
151                }
152                if (subSeqWeights == null) {
153                        subSeqWeights = generateWeights(process, allPossibleSubSeqs);
154                }
155                double weight = 0.0;
156                for (List<? extends Event<?>> subSeq : containedSubSeqs) {
157                        weight += subSeqWeights.get(subSeq);
158                }
159                return weight;
160        }
161
162        /**
163         * <p>
164         * Calculates the weights for all sequences passed to this function as
165         * defined by the stochastic process and stores them in a {@link Map}.
166         * </p>
167         *
168         * @param process
169         *            process used for weight calculation
170         * @param sequences
171         *            sequences for which the weights are calculated
172         * @return {@link Map} of weights
173         */
174        private static Map<List<? extends Event<?>>, Double> generateWeights(
175                        IStochasticProcess process,
176                        Collection<List<? extends Event<?>>> sequences) {
177                Map<List<? extends Event<?>>, Double> subSeqWeights = new LinkedHashMap<List<? extends Event<?>>, Double>();
178                double sum = 0.0;
179                for (List<? extends Event<?>> sequence : sequences) {
180                        double prob = 1.0;
181                        List<Event<?>> context = new LinkedList<Event<?>>();
182                        for (Event<?> event : sequence) {
183                                prob *= process.getProbability(context, event);
184                                context.add(event);
185                        }
186                        subSeqWeights.put(sequence, prob);
187                        sum += prob;
188                }
189                if (sum < 1.0) {
190                        for (Map.Entry<List<? extends Event<?>>, Double> entry : subSeqWeights
191                                        .entrySet()) {
192                                entry.setValue(entry.getValue() / sum);
193                        }
194                }
195                return subSeqWeights;
196        }
197
198        /**
199         * <p>
200         * Calculates the number of all existing sequences of a given length,
201         * regardless whether they are possible or not.
202         * </p>
203         *
204         * @param process
205         *            stochastic process whose symbols are the basis for this
206         *            calculation
207         * @param length
208         *            lenght of the sequences
209         * @return numStates^length
210         */
211        private static long numSequences(IStochasticProcess process, int length) {
212                return (long) Math.pow(process.getNumStates(), length);
213        }
214
215        /**
216         * <p>
217         * Creates a {@link Set} of all subsequences of a given length that are
218         * contained in a sequence collection.
219         * </p>
220         *
221         * @param sequences
222         *            sequences from which the subsequences are extracted
223         * @param length
224         *            length of the subsequences
225         * @return {@link Set} of all subsequences
226         */
227        private static Set<List<? extends Event<?>>> containedSubSequences(
228                        Collection<List<? extends Event<?>>> sequences, int length) {
229                Set<List<? extends Event<?>>> containedSubSeqs = new LinkedHashSet<List<? extends Event<?>>>();
230                for (List<? extends Event<?>> sequence : sequences) {
231                        List<Event<?>> subSeq = new LinkedList<Event<?>>();
232                        boolean minLengthReached = false;
233                        for (Event<?> event : sequence) {
234                                subSeq.add(event);
235                                if (!minLengthReached) {
236                                        if (subSeq.size() == length) {
237                                                minLengthReached = true;
238                                        }
239                                } else {
240                                        subSeq.remove(0);
241                                }
242                                if (minLengthReached) {
243                                        if (!containedSubSeqs.contains(subSeq)) {
244                                                containedSubSeqs.add(new LinkedList<Event<?>>(subSeq));
245                                        }
246                                }
247                        }
248                }
249                return containedSubSeqs;
250        }
251
252}
Note: See TracBrowser for help on using the repository browser.