1 | package de.uka.ipd.sdq.stoex.analyser.operations; |
2 | |
3 | import java.util.ArrayList; |
4 | import java.util.List; |
5 | |
6 | import de.uka.ipd.sdq.probfunction.math.IProbabilityFunctionFactory; |
7 | import de.uka.ipd.sdq.probfunction.math.IProbabilityMassFunction; |
8 | import de.uka.ipd.sdq.probfunction.math.ISample; |
9 | import de.uka.ipd.sdq.probfunction.math.IUnit; |
10 | import de.uka.ipd.sdq.probfunction.math.impl.ProbabilityFunctionFactoryImpl; |
11 | |
12 | /** |
13 | * Abstract class with interface for compare operations (e.g., equals, less, |
14 | * etc.). Includes some helper methods for probability functions. |
15 | * |
16 | * @author koziolek |
17 | * |
18 | */ |
19 | public abstract class CompareOperation { |
20 | |
21 | private static final Object TRUE_STRING = "true"; |
22 | private static final Object FALSE_STRING = "false"; |
23 | |
24 | /** |
25 | * Compares to objects that represent the left-hand side and the right-hand |
26 | * side of a comparison expression. |
27 | * |
28 | * @param left |
29 | * @param right |
30 | * @return |
31 | */ |
32 | public IProbabilityMassFunction compare(Object left, Object right) { |
33 | |
34 | // Assure proper handling of boolean values: |
35 | if (left instanceof String) { |
36 | if (((String) left).toLowerCase().equals(TRUE_STRING)) { |
37 | left = new Boolean(true); |
38 | } else if (((String) left).toLowerCase().equals(FALSE_STRING)) { |
39 | left = new Boolean(false); |
40 | } |
41 | } |
42 | if (right instanceof String) { |
43 | if (((String) right).toLowerCase().equals(TRUE_STRING)) { |
44 | right = new Boolean(true); |
45 | } else if (((String) right).toLowerCase().equals(FALSE_STRING)) { |
46 | right = new Boolean(false); |
47 | } |
48 | } |
49 | |
50 | // Propagate to the type-dependent handling: |
51 | if ((left instanceof Double) && (right instanceof Double)) { |
52 | return getComparePMF((Double) left, (Double) right); |
53 | } |
54 | if ((left instanceof IProbabilityMassFunction) |
55 | && (right instanceof Double)) { |
56 | return getComparePMF((IProbabilityMassFunction) left, |
57 | (Double) right); |
58 | } |
59 | if ((left instanceof Double) |
60 | && (right instanceof IProbabilityMassFunction)) { |
61 | return getComparePMF((Double) left, |
62 | (IProbabilityMassFunction) right); |
63 | } |
64 | if ((left instanceof IProbabilityMassFunction) |
65 | && (right instanceof IProbabilityMassFunction)) { |
66 | return getComparePMF((IProbabilityMassFunction) left, |
67 | (IProbabilityMassFunction) right); |
68 | } |
69 | if ((left instanceof String) && (right instanceof String)) { |
70 | return getComparePMF((String) left, (String) right); |
71 | } |
72 | if ((left instanceof String) |
73 | && (right instanceof IProbabilityMassFunction)) { |
74 | return getComparePMF((String) left, |
75 | (IProbabilityMassFunction) right); |
76 | } |
77 | if ((left instanceof Boolean) && (right instanceof Boolean)) { |
78 | return getComparePMF((Boolean) left, (Boolean) right); |
79 | } |
80 | |
81 | // Type not supported: |
82 | throw new UnsupportedOperationException(); |
83 | } |
84 | |
85 | /** |
86 | * Compares two probability mass functions pointwise. |
87 | * |
88 | * @param left |
89 | * @param right |
90 | * @return |
91 | */ |
92 | public double comparePointWise(IProbabilityMassFunction left, |
93 | IProbabilityMassFunction right, CompareOperation op) { |
94 | List<ISample> samplingPointsLeft = left.getSamples(); |
95 | List<ISample> samplingPointsRight = right.getSamples(); |
96 | double probabilitySum = 0.0; |
97 | for (ISample leftSamplingPoint : samplingPointsLeft) { |
98 | Object leftValue = leftSamplingPoint.getValue(); |
99 | for (ISample rightSamplingPoint : samplingPointsRight) { |
100 | Object rightValue = rightSamplingPoint.getValue(); |
101 | IProbabilityMassFunction boolPMF = op.compare(leftValue, |
102 | rightValue); |
103 | if ((Double) boolPMF.getSamples().get(1).getProbability() == 1.0) { |
104 | probabilitySum += leftSamplingPoint.getProbability() |
105 | * rightSamplingPoint.getProbability(); |
106 | } |
107 | } |
108 | } |
109 | return probabilitySum; |
110 | } |
111 | |
112 | /** |
113 | * Converts a probability into a boolean PMF. The probability is taken as |
114 | * value for true and 1-probability as value for false. |
115 | * |
116 | * @param left |
117 | * @param right |
118 | * @return |
119 | */ |
120 | public IProbabilityMassFunction getBoolPMF(double trueProb) { |
121 | IProbabilityFunctionFactory probFac = IProbabilityFunctionFactory.eINSTANCE; |
122 | |
123 | IUnit unit = probFac.createUnit("bool"); |
124 | |
125 | List<ISample> sampleList = new ArrayList<ISample>(); |
126 | sampleList.add(probFac.createSample(TRUE_STRING, trueProb)); |
127 | sampleList.add(probFac.createSample(FALSE_STRING, 1 - trueProb)); |
128 | |
129 | IProbabilityMassFunction boolPMF = probFac |
130 | .createProbabilityMassFunction(sampleList, unit, true); |
131 | |
132 | return boolPMF; |
133 | } |
134 | |
135 | /** |
136 | * Retrieves the probability for a given value from a PMF. |
137 | * |
138 | * @param iPMF |
139 | * @param valueToSeek |
140 | * @return |
141 | */ |
142 | public double getProbabilityForValue(IProbabilityMassFunction iPMF, |
143 | double valueToSeek) { |
144 | List<ISample> samplingPoints = iPMF.getSamples(); |
145 | for (ISample samplingPoint : samplingPoints) { |
146 | Object value = samplingPoint.getValue(); |
147 | if (value instanceof Number) { |
148 | Number valueNumber = (Number) samplingPoint.getValue(); |
149 | if (valueNumber.doubleValue() == valueToSeek) { |
150 | return samplingPoint.getProbability(); |
151 | } |
152 | } |
153 | } |
154 | return 0.0; |
155 | } |
156 | |
157 | /** |
158 | * Returns the sum of probabilities before a given value of a PMF. |
159 | * |
160 | * @param iPMF |
161 | * @param threshold |
162 | * @param includeThreshold |
163 | * @return |
164 | */ |
165 | public double getThresholdProbability(IProbabilityMassFunction iPMF, |
166 | double threshold, boolean includeThreshold) { |
167 | double probabilitySum = 0.0; |
168 | for (ISample sample : iPMF.getSamples()) { |
169 | Object sampleValueObject = sample.getValue(); |
170 | if (sampleValueObject instanceof Number) { |
171 | Double sampleValue = ((Number) sampleValueObject).doubleValue(); |
172 | if (sampleValue > threshold) { |
173 | return probabilitySum; |
174 | } else if (sampleValue == threshold) { |
175 | return (includeThreshold) ? probabilitySum |
176 | + sample.getProbability() : probabilitySum; |
177 | } else { |
178 | probabilitySum += sample.getProbability(); |
179 | } |
180 | } else |
181 | throw new UnsupportedOperationException(); |
182 | } |
183 | return 0.0; |
184 | } |
185 | |
186 | /** |
187 | * Compares two boolean values. |
188 | * |
189 | * @param left |
190 | * @param right |
191 | * @return |
192 | */ |
193 | protected abstract IProbabilityMassFunction getComparePMF(boolean left, |
194 | boolean right); |
195 | |
196 | /** |
197 | * Compares two doubles. |
198 | * |
199 | * @param left |
200 | * @param right |
201 | * @return |
202 | */ |
203 | protected abstract IProbabilityMassFunction getComparePMF(double left, |
204 | double right); |
205 | |
206 | /** |
207 | * Compares a PMF with a double. |
208 | * |
209 | * @param left |
210 | * @param right |
211 | * @return |
212 | */ |
213 | protected abstract IProbabilityMassFunction getComparePMF(double left, |
214 | IProbabilityMassFunction right); |
215 | |
216 | /** |
217 | * Compares a PMF with a double. |
218 | * |
219 | * @param left |
220 | * @param right |
221 | * @return |
222 | */ |
223 | protected abstract IProbabilityMassFunction getComparePMF( |
224 | IProbabilityMassFunction left, double right); |
225 | |
226 | /** |
227 | * Compares two PMFs. |
228 | * |
229 | * @param left |
230 | * @param right |
231 | * @return |
232 | */ |
233 | protected abstract IProbabilityMassFunction getComparePMF( |
234 | IProbabilityMassFunction left, IProbabilityMassFunction right); |
235 | |
236 | /** |
237 | * Compares a String and an EnumPMF |
238 | * |
239 | * @param left |
240 | * @param right |
241 | * @return |
242 | */ |
243 | protected abstract IProbabilityMassFunction getComparePMF(String left, |
244 | IProbabilityMassFunction right); |
245 | |
246 | /** |
247 | * Compares two Strings. |
248 | * |
249 | * @param left |
250 | * @param right |
251 | * @return |
252 | */ |
253 | protected abstract IProbabilityMassFunction getComparePMF(String left, |
254 | String right); |
255 | |
256 | /** |
257 | * This method inverts a BoolPMF as required by a NOT statement. |
258 | * This method would be better placed elsewhere, but it accesses internal knowledge how |
259 | * a BoolPMF is represented as a IProbabilityMassFunction which is only available in this class. |
260 | * @see #getBoolPMF(double). |
261 | * @param function |
262 | * @return The inverted function, assuming this is a BoolPMF. |
263 | * @throws UnsupportedOperationException if the passed PMF is not a BoolPMF, |
264 | * i.e. if it does not contain the String literals "TRUE" and "FALSE". |
265 | */ |
266 | public static IProbabilityMassFunction invertBoolPMF(IProbabilityMassFunction function){ |
267 | //check whether this is a BoolPMF, i.e. two samples with labels TRUE and FALSE. |
268 | List<ISample> samples = function.getSamples(); |
269 | if (samples.size() == 2){ |
270 | ISample sample1 = samples.get(0); |
271 | ISample sample2 = samples.get(1); |
272 | |
273 | ISample sampleTrue = null; |
274 | ISample sampleFalse = null; |
275 | |
276 | if (sampleIsTrue(sample1)){ |
277 | if (sampleIsFalse(sample2)){ |
278 | sampleTrue = sample1; |
279 | sampleFalse = sample2; |
280 | } |
281 | } else if (sampleIsFalse(sample1)){ |
282 | if (sampleIsTrue(sample2)){ |
283 | sampleTrue = sample2; |
284 | sampleFalse = sample1; |
285 | } |
286 | } |
287 | |
288 | if (sampleTrue != null && sampleFalse != null){ |
289 | |
290 | IProbabilityFunctionFactory probFac = ProbabilityFunctionFactoryImpl.eINSTANCE; |
291 | |
292 | //is probably never used. |
293 | IUnit unit = probFac.createUnit("bool"); |
294 | |
295 | List<ISample> sampleList = new ArrayList<ISample>(); |
296 | |
297 | ISample newTrueSample = probFac.createSample(true, sampleFalse.getProbability()); |
298 | ISample newFalseSample = probFac.createSample(false, sampleTrue.getProbability()); |
299 | sampleList.add(newTrueSample); |
300 | sampleList.add(newFalseSample); |
301 | |
302 | IProbabilityMassFunction boolPMF = probFac |
303 | .createProbabilityMassFunction(sampleList, unit, true); |
304 | |
305 | return boolPMF; |
306 | |
307 | } |
308 | } |
309 | throw new UnsupportedOperationException("Cannot invert PMF "+function.toString()+" as it is no valid BoolPMF."); |
310 | } |
311 | |
312 | private static boolean sampleIsTrue(ISample sample) { |
313 | if (sample.getValue() instanceof Boolean) |
314 | return (Boolean)sample.getValue(); |
315 | return TRUE_STRING.equals(sample.getValue()); |
316 | } |
317 | |
318 | private static boolean sampleIsFalse(ISample sample) { |
319 | if (sample.getValue() instanceof Boolean) |
320 | return !(Boolean)sample.getValue(); |
321 | return FALSE_STRING.equals(sample.getValue()); |
322 | } |
323 | } |