1 | package de.uka.ipd.sdq.probfunction.math.impl; |
2 | |
3 | import java.util.ArrayList; |
4 | import java.util.Arrays; |
5 | import java.util.Collections; |
6 | import java.util.HashMap; |
7 | import java.util.List; |
8 | |
9 | import org.eclipse.emf.common.util.EList; |
10 | |
11 | import de.uka.ipd.sdq.probfunction.BoxedPDF; |
12 | import de.uka.ipd.sdq.probfunction.ContinuousSample; |
13 | import de.uka.ipd.sdq.probfunction.ExponentialDistribution; |
14 | import de.uka.ipd.sdq.probfunction.GammaDistribution; |
15 | import de.uka.ipd.sdq.probfunction.LognormalDistribution; |
16 | import de.uka.ipd.sdq.probfunction.NormalDistribution; |
17 | import de.uka.ipd.sdq.probfunction.ProbabilityDensityFunction; |
18 | import de.uka.ipd.sdq.probfunction.ProbabilityMassFunction; |
19 | import de.uka.ipd.sdq.probfunction.ProbfunctionFactory; |
20 | import de.uka.ipd.sdq.probfunction.Sample; |
21 | import de.uka.ipd.sdq.probfunction.SamplePDF; |
22 | import de.uka.ipd.sdq.probfunction.math.IBoxedPDF; |
23 | import de.uka.ipd.sdq.probfunction.math.IContinousPDF; |
24 | import de.uka.ipd.sdq.probfunction.math.IContinuousSample; |
25 | import de.uka.ipd.sdq.probfunction.math.IExponentialDistribution; |
26 | import de.uka.ipd.sdq.probfunction.math.IGammaDistribution; |
27 | import de.uka.ipd.sdq.probfunction.math.ILognormalDistribution; |
28 | import de.uka.ipd.sdq.probfunction.math.INormalDistribution; |
29 | import de.uka.ipd.sdq.probfunction.math.IPDFFactory; |
30 | import de.uka.ipd.sdq.probfunction.math.IProbabilityDensityFunction; |
31 | import de.uka.ipd.sdq.probfunction.math.IProbabilityFunctionFactory; |
32 | import de.uka.ipd.sdq.probfunction.math.IProbabilityMassFunction; |
33 | import de.uka.ipd.sdq.probfunction.math.IRandomGenerator; |
34 | import de.uka.ipd.sdq.probfunction.math.ISample; |
35 | import de.uka.ipd.sdq.probfunction.math.ISamplePDF; |
36 | import de.uka.ipd.sdq.probfunction.math.IUnit; |
37 | import de.uka.ipd.sdq.probfunction.math.apache.impl.PDFFactory; |
38 | import de.uka.ipd.sdq.probfunction.math.exception.DoubleSampleException; |
39 | import de.uka.ipd.sdq.probfunction.math.exception.FunctionNotInTimeDomainException; |
40 | import de.uka.ipd.sdq.probfunction.math.exception.NegativeDistanceException; |
41 | import de.uka.ipd.sdq.probfunction.math.exception.ProbabilitySumNotOneException; |
42 | import de.uka.ipd.sdq.probfunction.math.exception.UnknownPDFTypeException; |
43 | import de.uka.ipd.sdq.probfunction.math.util.MathTools; |
44 | import flanagan.complex.Complex; |
45 | |
46 | /** |
47 | * @author Ihssane, martens |
48 | * |
49 | */ |
50 | public class ProbabilityFunctionFactoryImpl implements |
51 | IProbabilityFunctionFactory { |
52 | |
53 | public static final String DEFAULT_UNIT_NAME = "ms"; |
54 | private ProbfunctionFactory eFactory = ProbfunctionFactory.eINSTANCE; |
55 | private IPDFFactory pdfFactory; |
56 | |
57 | /** |
58 | * can be overwritten by {@link #setRandomGenerator(IRandomGenerator)} |
59 | * to use a predefined random generator in all methods. |
60 | * Otherwise, the default is used. |
61 | */ |
62 | private IRandomGenerator randomGenerator = new DefaultRandomGenerator(); |
63 | |
64 | protected final static ProbabilityFunctionFactoryImpl factoryInstance = new ProbabilityFunctionFactoryImpl( |
65 | new PDFFactory()); |
66 | |
67 | protected ProbabilityFunctionFactoryImpl(IPDFFactory pdfFactory) { |
68 | this.pdfFactory = pdfFactory; |
69 | } |
70 | |
71 | public IPDFFactory getPDFFactory() { |
72 | return pdfFactory; |
73 | } |
74 | |
75 | public void setPDFFactory(IPDFFactory pdfFactory) { |
76 | this.pdfFactory = pdfFactory; |
77 | } |
78 | |
79 | public IBoxedPDF transformToBoxedPDF(ProbabilityDensityFunction epdf) |
80 | throws ProbabilitySumNotOneException, DoubleSampleException { |
81 | return transformToBoxedPDF(epdf,this.randomGenerator); |
82 | } |
83 | |
84 | public IBoxedPDF transformToBoxedPDF(ProbabilityDensityFunction epdf, |
85 | IRandomGenerator randomNumberGenerator) |
86 | throws ProbabilitySumNotOneException, DoubleSampleException { |
87 | // TODO: IUnit unit = transformToUnit(epdf.getUnitSpecification()); |
88 | List<IContinuousSample> samples = new ArrayList<IContinuousSample>(); |
89 | |
90 | if (epdf instanceof BoxedPDF) { |
91 | for (Object s : ((BoxedPDF) epdf).getSamples()) { |
92 | samples.add(transformToContinuousSample((ContinuousSample) s)); |
93 | } |
94 | } else if (epdf instanceof SamplePDF) { |
95 | int i = 1; |
96 | for (Object v : ((SamplePDF) epdf).getValues()) { |
97 | samples.add(createContinuousSample(i |
98 | * ((SamplePDF) epdf).getDistance(), (Double) v)); |
99 | i++; |
100 | } |
101 | } |
102 | return createBoxedPDF(samples, randomNumberGenerator, /* TODO:Unit */null); |
103 | } |
104 | |
105 | public ISamplePDF transformToSamplePDF(ProbabilityDensityFunction epdf) |
106 | throws UnknownPDFTypeException, ProbabilitySumNotOneException, |
107 | DoubleSampleException { |
108 | return transformToSamplePDF(epdf,this.randomGenerator); |
109 | } |
110 | |
111 | public ISamplePDF transformToSamplePDF(ProbabilityDensityFunction epdf, IRandomGenerator randomGenerator) |
112 | throws UnknownPDFTypeException, ProbabilitySumNotOneException, |
113 | DoubleSampleException { |
114 | if (epdf instanceof SamplePDF) { |
115 | SamplePDF spdf = (SamplePDF) epdf; |
116 | double distance = spdf.getDistance(); |
117 | // TODO: Unit IUnit unit = |
118 | // transformToUnit(spdf.getUnitSpecification()); |
119 | // TODO: Fix this after PCM4 migration |
120 | //List<Double> values = new ArrayList<Double>((List<Double>) spdf |
121 | // .getValues()); |
122 | List<Double> values = new ArrayList<Double>(); |
123 | return createSamplePDFFromDouble(distance, values, /* TODO:Unit */ |
124 | null,randomGenerator); |
125 | } else { |
126 | IBoxedPDF bpdf = transformToBoxedPDF(epdf,randomGenerator); |
127 | return transformBoxedToSamplePDF(bpdf); |
128 | } |
129 | } |
130 | |
131 | public IProbabilityMassFunction transformToPMF(ProbabilityMassFunction epmf) { |
132 | return transformToPMF(epmf,this.randomGenerator); |
133 | } |
134 | |
135 | @SuppressWarnings("unchecked") |
136 | public IProbabilityMassFunction transformToPMF(ProbabilityMassFunction epmf, |
137 | IRandomGenerator randomGenerator) { |
138 | // TODO:Unit! IUnit unit = transformToUnit(epmf.getUnitSpecification()); |
139 | boolean hasOrderedDomain = epmf.isOrderedDomain(); |
140 | IProbabilityMassFunction pmf = new ProbabilityMassFunctionImpl( |
141 | new ArrayList<ISample>(), /* TODO:Unit */null, hasOrderedDomain, false, randomGenerator); |
142 | List samples = new ArrayList(); |
143 | for (Object s : epmf.getSamples()) { |
144 | Sample sample = (Sample) s; |
145 | samples.add(transformToSample(sample)); |
146 | } |
147 | |
148 | pmf.setSamples(samples); |
149 | return pmf; |
150 | } |
151 | |
152 | public IBoxedPDF createBoxedPDF(List<IContinuousSample> samples, |
153 | IUnit unit) |
154 | throws DoubleSampleException |
155 | { |
156 | return createBoxedPDF(samples, this.randomGenerator, unit); |
157 | } |
158 | |
159 | public IBoxedPDF createBoxedPDF(List<IContinuousSample> samples, |
160 | IRandomGenerator randomGenerator, |
161 | IUnit unit) |
162 | throws DoubleSampleException { |
163 | BoxedPDFImpl bpdf = new BoxedPDFImpl(unit,randomGenerator); |
164 | bpdf.setSamples(samples); |
165 | return bpdf; |
166 | } |
167 | |
168 | public IBoxedPDF createBoxedPDF(List<IContinuousSample> samples, |
169 | IUnit unit, IRandomGenerator generator) |
170 | throws DoubleSampleException { |
171 | BoxedPDFImpl bpdf = new BoxedPDFImpl(unit, generator); |
172 | bpdf.setSamples(samples); |
173 | return new BoxedPDFImpl(unit, generator); |
174 | } |
175 | |
176 | public IContinuousSample createContinuousSample(double value, double d) { |
177 | return new ContinuousSampleImpl(value, d); |
178 | } |
179 | |
180 | public IUnit createDefaultUnit() { |
181 | return new UnitImpl(DEFAULT_UNIT_NAME); |
182 | } |
183 | |
184 | public ISamplePDF createDiracImpulse(int numOfSamplingPoints, |
185 | double distance, IUnit unit) { |
186 | return createImpulseAt(0, numOfSamplingPoints, distance, unit); |
187 | } |
188 | |
189 | public ISamplePDF createImpulseAt(int pos, int numOfSamplingPoints, |
190 | double distance, IUnit unit) { |
191 | assert (pos < numOfSamplingPoints); |
192 | |
193 | List<Complex> zeroList = createZeroList(numOfSamplingPoints); |
194 | zeroList.get(pos).setReal(1.0); |
195 | return createSamplePDFFromComplex(distance, zeroList, false, unit); |
196 | |
197 | } |
198 | |
199 | private List<Complex> createZeroList(int numOfSamplingPoints) { |
200 | List<Complex> resultList = new ArrayList<Complex>(); |
201 | for (int i = 0; i < numOfSamplingPoints; i++) { |
202 | resultList.add(new Complex(0, 0)); |
203 | } |
204 | return resultList; |
205 | } |
206 | |
207 | @Override |
208 | public IProbabilityMassFunction createProbabilityMassFunction( |
209 | List<ISample> samples, IUnit unit, boolean hasOrderedDomain) { |
210 | return new ProbabilityMassFunctionImpl(samples, unit, hasOrderedDomain, |
211 | false, this.randomGenerator); |
212 | } |
213 | |
214 | public IProbabilityMassFunction createPMFFromMeasurements( |
215 | Boolean[] measurements, IUnit unit, boolean hasOrderedDomain) { |
216 | HashMap<Boolean, Integer> times = new HashMap<Boolean, Integer>(); |
217 | List<Boolean> measurementsList = Arrays.asList(measurements); |
218 | for (Boolean i : measurementsList) { |
219 | int oldValue = times.get(i) == null ? 0 : times.get(i); |
220 | times.put(i, ++oldValue); |
221 | } |
222 | List<ISample> samples = createPMFFromList(times, measurementsList |
223 | .size()); |
224 | return createProbabilityMassFunction(samples, unit, hasOrderedDomain); |
225 | } |
226 | |
227 | public IProbabilityMassFunction createPMFFromMeasurements( |
228 | Double[] measurements, double epsilon, IUnit unit, |
229 | boolean hasOrderedDomain) { |
230 | HashMap<Double, Integer> times = new HashMap<Double, Integer>(); |
231 | List<Double> measurementsList = Arrays.asList(measurements); |
232 | List<Integer> compared = new ArrayList<Integer>(); |
233 | int index1 = 0; |
234 | for (Double d1 : measurementsList) { |
235 | int index = 0; |
236 | if (compared.contains(index1)) { |
237 | index1++; |
238 | continue; |
239 | } |
240 | for (Double d2 : measurementsList) { |
241 | if (Math.abs(d1 - d2) < epsilon && !compared.contains(index)) { |
242 | int oldValue = times.get(d1) == null ? 0 : times.get(d1); |
243 | times.put(d1, ++oldValue); |
244 | compared.add(index); |
245 | } |
246 | index++; |
247 | } |
248 | index1++; |
249 | } |
250 | List<ISample> samples = createPMFFromList(times, measurementsList |
251 | .size()); |
252 | return createProbabilityMassFunction(samples, unit, hasOrderedDomain); |
253 | } |
254 | |
255 | public IProbabilityMassFunction createPMFFromMeasurements( |
256 | String[] measurements, IUnit unit, boolean hasOrderedDomain) { |
257 | HashMap<String, Integer> times = new HashMap<String, Integer>(); |
258 | List<String> measurementsList = Arrays.asList(measurements); |
259 | for (String i : measurementsList) { |
260 | int oldValue = times.get(i) == null ? 0 : times.get(i); |
261 | times.put(i, ++oldValue); |
262 | } |
263 | List<ISample> samples = createPMFFromList(times, measurementsList |
264 | .size()); |
265 | return createProbabilityMassFunction(samples, unit, hasOrderedDomain); |
266 | } |
267 | |
268 | public IProbabilityMassFunction createPMFFromMeasurements( |
269 | Integer[] measurements, IUnit unit, boolean hasOrderedDomain) { |
270 | HashMap<Integer, Integer> times = new HashMap<Integer, Integer>(); |
271 | List<Integer> measurementsList = Arrays.asList(measurements); |
272 | for (Integer i : measurementsList) { |
273 | int oldValue = times.get(i) == null ? 0 : times.get(i); |
274 | times.put(i, ++oldValue); |
275 | } |
276 | List<ISample> samples = createPMFFromList(times, measurementsList |
277 | .size()); |
278 | return createProbabilityMassFunction(samples, unit, hasOrderedDomain); |
279 | } |
280 | |
281 | private List<ISample> createPMFFromList( |
282 | HashMap<? extends Object, Integer> map, int count) { |
283 | List<ISample> samples = new ArrayList<ISample>(); |
284 | for (Object value : map.keySet()) |
285 | samples.add(createSample(value, map.get(value) * 1.0 / count)); |
286 | |
287 | return samples; |
288 | } |
289 | |
290 | public ISample createSample(Object value, double probability) { |
291 | return new SampleImpl(value, probability); |
292 | } |
293 | |
294 | public ISamplePDF createSamplePDFFromComplex(double distance, |
295 | List<Complex> values, IUnit unit) { |
296 | ISamplePDF spdf = new SamplePDFImpl(distance, unit, randomGenerator); |
297 | spdf.setValues(values, false); |
298 | return spdf; |
299 | } |
300 | |
301 | public ISamplePDF createSamplePDFFromComplex(double distance, |
302 | List<Complex> samples, boolean isInFrequencyDomain, IUnit unit) { |
303 | ISamplePDF spdf = new SamplePDFImpl(distance, unit, isInFrequencyDomain, this.randomGenerator); |
304 | spdf.setValues(samples, isInFrequencyDomain); |
305 | return spdf; |
306 | } |
307 | |
308 | public ISamplePDF createSamplePDFFromComplex(double distance, |
309 | List<Complex> samples, IUnit unit, IRandomGenerator generator) { |
310 | ISamplePDF spdf = new SamplePDFImpl(distance, unit, generator); |
311 | spdf.setValues(samples, false); |
312 | return spdf; |
313 | } |
314 | |
315 | public ISamplePDF createSamplePDFFromComplex(double distance, |
316 | List<Complex> samples, boolean isInFrequencyDomain, IUnit unit, |
317 | IRandomGenerator generator) { |
318 | ISamplePDF spdf = new SamplePDFImpl(distance, unit, |
319 | isInFrequencyDomain, generator); |
320 | spdf.setValues(samples, isInFrequencyDomain); |
321 | return spdf; |
322 | } |
323 | |
324 | public ISamplePDF createSamplePDFFromDouble(double distance, |
325 | List<Double> values, IUnit unit) { |
326 | ISamplePDF spdf = new SamplePDFImpl(distance, unit, this.randomGenerator); |
327 | spdf.setValuesAsDouble(values); |
328 | return spdf; |
329 | } |
330 | |
331 | public ISamplePDF createSamplePDFFromDouble(double distance, |
332 | List<Double> values, boolean isInFrequencyDomain, IUnit unit) { |
333 | ISamplePDF spdf = new SamplePDFImpl(distance, unit, isInFrequencyDomain, this.randomGenerator); |
334 | spdf.setValuesAsDouble(values); |
335 | return spdf; |
336 | } |
337 | |
338 | public ISamplePDF createSamplePDFFromDouble(double distance, |
339 | List<Double> values, IUnit unit, IRandomGenerator generator) { |
340 | ISamplePDF spdf = new SamplePDFImpl(distance, unit, generator); |
341 | spdf.setValuesAsDouble(values); |
342 | return spdf; |
343 | } |
344 | |
345 | public ISamplePDF createSamplePDFFromDouble(double distance, |
346 | List<Double> values, boolean isInFrequencyDomain, IUnit unit, |
347 | IRandomGenerator generator) { |
348 | ISamplePDF spdf = new SamplePDFImpl(distance, unit, |
349 | isInFrequencyDomain, generator); |
350 | spdf.setValuesAsDouble(values); |
351 | return spdf; |
352 | } |
353 | |
354 | public ISamplePDF createSamplePDFFromMeasurements(double distance, |
355 | List<Double> measurements, IUnit unit) { |
356 | Collections.sort(measurements); |
357 | List<Double> samples = new ArrayList<Double>(); |
358 | HashMap<Integer, Integer> timesMap = new HashMap<Integer, Integer>(); |
359 | |
360 | int maxPos = 0; |
361 | |
362 | for (Double d : measurements) { |
363 | int pos = (int) (d / distance); |
364 | double rest = (d % distance) / distance; |
365 | if (rest > 0.5) |
366 | pos += 1; |
367 | maxPos = pos > maxPos ? pos : maxPos; |
368 | Integer value = timesMap.get(pos); |
369 | if (value == null) |
370 | value = new Integer(0); |
371 | value++; |
372 | timesMap.put(pos, value); |
373 | } |
374 | |
375 | for (int i = 0; i <= maxPos; i++) { |
376 | Integer value = timesMap.get(i); |
377 | if (value == null) { |
378 | samples.add(0.0); |
379 | } else { |
380 | samples.add((double) value / (double) measurements.size()); |
381 | } |
382 | } |
383 | |
384 | return createSamplePDFFromDouble(distance, samples, unit); |
385 | } |
386 | |
387 | public IUnit createUnit(String unitName) { |
388 | return new UnitImpl(unitName); |
389 | } |
390 | |
391 | public ISamplePDF createZeroFunction(int numOfSamplingPoints, |
392 | double distance, IUnit unit) { |
393 | List<Complex> zeroList = createZeroList(numOfSamplingPoints); |
394 | return createSamplePDFFromComplex(distance, zeroList, false, unit); |
395 | } |
396 | |
397 | public IBoxedPDF transformToBoxedPDF(IProbabilityDensityFunction pdf) |
398 | throws UnknownPDFTypeException, DoubleSampleException, |
399 | FunctionNotInTimeDomainException { |
400 | IBoxedPDF resultPDF; |
401 | if (pdf instanceof IBoxedPDF) { |
402 | resultPDF = (IBoxedPDF) pdf; |
403 | } else if (pdf instanceof ISamplePDF) { |
404 | resultPDF = transformSampledToBoxedPDF((ISamplePDF) pdf); |
405 | } else if (pdf instanceof IContinousPDF){ |
406 | resultPDF = transformContinuousToBoxedPDF((IContinousPDF) pdf); |
407 | } else { |
408 | throw new UnknownPDFTypeException(pdf); |
409 | } |
410 | return resultPDF; |
411 | } |
412 | |
413 | @SuppressWarnings("unchecked") |
414 | public BoxedPDF transformToModelBoxedPDF(IProbabilityDensityFunction pdf) |
415 | throws UnknownPDFTypeException, DoubleSampleException, |
416 | FunctionNotInTimeDomainException { |
417 | IBoxedPDF boxedPDF = transformToBoxedPDF(pdf); |
418 | |
419 | BoxedPDF ePDF = eFactory.createBoxedPDF(); |
420 | EList list = ePDF.getSamples(); |
421 | |
422 | // TODO:Unit! |
423 | // ePDF.setUnitSpecification(transformToModelUnitSpecification(pdf.getUnit())); |
424 | |
425 | for (IContinuousSample s : boxedPDF.getSamples()) |
426 | list.add(transformToModelContinuousSample(s)); |
427 | return ePDF; |
428 | } |
429 | |
430 | public ProbabilityDensityFunction transformToModelPDF( |
431 | IProbabilityDensityFunction pdf) throws UnknownPDFTypeException, |
432 | DoubleSampleException, FunctionNotInTimeDomainException { |
433 | ProbabilityDensityFunction ePDF; |
434 | |
435 | if (pdf instanceof ISamplePDF) { |
436 | ePDF = transformToModelSamplePDF(pdf); |
437 | } else if (pdf instanceof IBoxedPDF) { |
438 | ePDF = transformToModelBoxedPDF(pdf); |
439 | } else if (pdf instanceof IExponentialDistribution){ |
440 | ExponentialDistribution expPDF = eFactory.createExponentialDistribution(); |
441 | expPDF.setRate(((IExponentialDistribution)pdf).getRate()); |
442 | ePDF = expPDF; |
443 | } else if (pdf instanceof IGammaDistribution){ |
444 | GammaDistribution gamma = eFactory.createGammaDistribution(); |
445 | gamma.setAlpha(((IGammaDistribution)pdf).getAlpha()); |
446 | gamma.setTheta(((IGammaDistribution)pdf).getTheta()); |
447 | ePDF = gamma; |
448 | } else if (pdf instanceof ILognormalDistribution){ |
449 | LognormalDistribution lognorm = eFactory.createLognormalDistribution(); |
450 | lognorm.setMu(((ILognormalDistribution)pdf).getMu()); |
451 | lognorm.setSigma(((ILognormalDistribution)pdf).getSigma()); |
452 | ePDF = lognorm; |
453 | } else if (pdf instanceof INormalDistribution){ |
454 | NormalDistribution norm = eFactory.createNormalDistribution(); |
455 | norm.setMu(((INormalDistribution)pdf).getMean()); |
456 | norm.setSigma(((INormalDistribution)pdf).getSigma()); |
457 | ePDF = norm; |
458 | } else { |
459 | throw new UnknownPDFTypeException(pdf); |
460 | } |
461 | return ePDF; |
462 | } |
463 | |
464 | @SuppressWarnings("unchecked") |
465 | public ProbabilityMassFunction transformToModelPMF( |
466 | IProbabilityMassFunction pmf) { |
467 | ProbabilityMassFunction epmf = eFactory.createProbabilityMassFunction(); |
468 | EList list = epmf.getSamples(); |
469 | |
470 | for (ISample s : pmf.getSamples()) |
471 | list.add(transformToModelSample(s)); |
472 | // TODO:Unit! |
473 | // epmf.setUnitSpecification(transformToModelUnitSpecification(pmf.getUnit())); |
474 | epmf.setOrderedDomain(pmf.hasOrderedDomain()); |
475 | return epmf; |
476 | } |
477 | |
478 | @SuppressWarnings("unchecked") |
479 | public SamplePDF transformToModelSamplePDF(IProbabilityDensityFunction pdf) |
480 | throws UnknownPDFTypeException { |
481 | ISamplePDF samplePDF = transformToSamplePDF(pdf); |
482 | SamplePDF ePDF = eFactory.createSamplePDF(); |
483 | EList list = ePDF.getValues(); |
484 | |
485 | for (Complex d : samplePDF.getValues()) |
486 | list.add(d.getReal()); |
487 | |
488 | // TODO:Unit! |
489 | // ePDF.setUnitSpecification(transformToModelUnitSpecification(pdf.getUnit())); |
490 | |
491 | ePDF.setDistance(samplePDF.getDistance()); |
492 | |
493 | return ePDF; |
494 | } |
495 | |
496 | public IProbabilityDensityFunction transformToPDF( |
497 | ProbabilityDensityFunction ePDF) throws UnknownPDFTypeException, |
498 | ProbabilitySumNotOneException, DoubleSampleException { |
499 | return transformToPDF(ePDF,this.randomGenerator); |
500 | } |
501 | |
502 | /** |
503 | * TODO: support Pois, Binom, UniInt and UniDouble. They need to be added to the probfunction metamodel and then handled here. |
504 | */ |
505 | public IProbabilityDensityFunction transformToPDF( |
506 | ProbabilityDensityFunction ePDF, |
507 | IRandomGenerator randomGenerator) throws UnknownPDFTypeException, |
508 | ProbabilitySumNotOneException, DoubleSampleException { |
509 | IProbabilityDensityFunction pdf; |
510 | |
511 | if (ePDF instanceof SamplePDF) { |
512 | pdf = transformToSamplePDF(ePDF,randomGenerator); |
513 | } else if (ePDF instanceof BoxedPDF) { |
514 | pdf = transformToBoxedPDF(ePDF,randomGenerator); |
515 | } else if (ePDF instanceof de.uka.ipd.sdq.probfunction.ExponentialDistribution){ |
516 | pdf = pdfFactory.createExponentialDistribution(((de.uka.ipd.sdq.probfunction.ExponentialDistribution)ePDF).getRate()); |
517 | } else if (ePDF instanceof de.uka.ipd.sdq.probfunction.GammaDistribution){ |
518 | pdf = pdfFactory.createGammaDistribution(((de.uka.ipd.sdq.probfunction.GammaDistribution)ePDF).getAlpha(),((de.uka.ipd.sdq.probfunction.GammaDistribution)ePDF).getTheta()); |
519 | } else if (ePDF instanceof de.uka.ipd.sdq.probfunction.LognormalDistribution){ |
520 | pdf = pdfFactory.createLognormalDistribution(((de.uka.ipd.sdq.probfunction.LognormalDistribution)ePDF).getMu(),((de.uka.ipd.sdq.probfunction.LognormalDistribution)ePDF).getSigma()); |
521 | } else if (ePDF instanceof de.uka.ipd.sdq.probfunction.NormalDistribution){ |
522 | pdf = pdfFactory.createNormalDistribution(((de.uka.ipd.sdq.probfunction.NormalDistribution)ePDF).getMu(),((de.uka.ipd.sdq.probfunction.NormalDistribution)ePDF).getSigma()); |
523 | } else { |
524 | throw new UnknownPDFTypeException(ePDF); |
525 | } |
526 | return pdf; |
527 | } |
528 | |
529 | public ISamplePDF transformToSamplePDF(IProbabilityDensityFunction pdf) |
530 | throws UnknownPDFTypeException { |
531 | ISamplePDF resultPDF; |
532 | if (pdf instanceof ISamplePDF) { |
533 | resultPDF = (ISamplePDF) pdf; |
534 | } else if (pdf instanceof IBoxedPDF) { |
535 | resultPDF = transformBoxedToSamplePDF((IBoxedPDF) pdf); |
536 | } else if (pdf != null) { |
537 | throw new UnknownPDFTypeException(pdf); |
538 | } else { |
539 | return null; |
540 | } |
541 | return resultPDF; |
542 | } |
543 | |
544 | public ISamplePDF transformToSamplePDF(IProbabilityDensityFunction pdf, |
545 | double newDistance) throws UnknownPDFTypeException, |
546 | NegativeDistanceException, FunctionNotInTimeDomainException { |
547 | ISamplePDF resultPDF; |
548 | if (pdf instanceof ISamplePDF) { |
549 | resultPDF = ((ISamplePDF) pdf) |
550 | .getFunctionWithNewDistance(newDistance); |
551 | } else if (pdf instanceof IBoxedPDF) { |
552 | resultPDF = transformBoxedToSamplePDF((IBoxedPDF) pdf, newDistance); |
553 | } else if (pdf != null) { |
554 | throw new UnknownPDFTypeException(pdf); |
555 | } else { |
556 | return null; |
557 | } |
558 | return resultPDF; |
559 | } |
560 | |
561 | public IContinuousSample transformToContinuousSample( |
562 | ContinuousSample eSample) { |
563 | IContinuousSample sample = createContinuousSample(eSample.getValue(), |
564 | eSample.getProbability()); |
565 | return sample; |
566 | } |
567 | |
568 | public ContinuousSample transformToModelContinuousSample( |
569 | IContinuousSample sample) { |
570 | ContinuousSample eSample = eFactory.createContinuousSample(); |
571 | eSample.setProbability(sample.getProbability()); |
572 | eSample.setValue(sample.getValue()); |
573 | return eSample; |
574 | } |
575 | |
576 | public Sample transformToModelSample(ISample sample) { |
577 | Sample eSample = eFactory.createSample(); |
578 | eSample.setProbability(sample.getProbability()); |
579 | eSample.setValue(sample.getValue()); |
580 | return eSample; |
581 | } |
582 | |
583 | public String transformToModelUnitSpecification(IUnit unit) { |
584 | return unit.getUnitName(); |
585 | } |
586 | |
587 | public ISample transformToSample(Sample eSample) { |
588 | ISample sample = createSample(eSample.getValue(), eSample |
589 | .getProbability()); |
590 | return sample; |
591 | } |
592 | |
593 | public IUnit transformToUnit(String unitSpecification) { |
594 | IUnit unit = createDefaultUnit(); |
595 | unit.setUnitName(unitSpecification); |
596 | return unit; |
597 | } |
598 | |
599 | public static ProbabilityFunctionFactoryImpl getInstance() { |
600 | return factoryInstance; |
601 | } |
602 | |
603 | private ISamplePDF transformBoxedToSamplePDF(IBoxedPDF pdf) { |
604 | List<Double> values = continuousSamplesToDoubles(pdf.getSamples()); |
605 | List<Double> newValues = new ArrayList<Double>(); |
606 | double distance = MathTools.gcd(values); |
607 | double halfDistance = distance / 2; |
608 | double start = 0; |
609 | |
610 | // the first value |
611 | int flag = 1; |
612 | double np = 0.0; |
613 | for (IContinuousSample s : pdf.getSamples()) { |
614 | int times = (int) Math.round((s.getValue() - start) / halfDistance); |
615 | for (int i = 0; i < times; i++) { |
616 | if (flag == 1) { |
617 | np += s.getProbability() / times; |
618 | newValues.add(np); |
619 | flag = 0; |
620 | } else { |
621 | np = s.getProbability() / times; |
622 | flag++; |
623 | } |
624 | } |
625 | start = s.getValue(); |
626 | } |
627 | if (flag == 1) |
628 | newValues.add(np); |
629 | return createSamplePDFFromDouble(distance, newValues, pdf.getUnit()); |
630 | } |
631 | |
632 | public ISamplePDF transformBoxedToSamplePDF(IBoxedPDF bpdf, double distance) { |
633 | if (bpdf.getSamples().size() == 0) |
634 | return createSamplePDFFromComplex(distance, |
635 | new ArrayList<Complex>(), bpdf.getUnit()); |
636 | |
637 | double maxValue = bpdf.getSamples().get(bpdf.getSamples().size() - 1).getValue(); |
638 | double currentNewSample = distance / 2; |
639 | int index = 0; |
640 | List<IContinuousSample> samples = bpdf.getSamples(); |
641 | List<Double> newSamples = new ArrayList<Double>(); |
642 | double newProb = 0.0; |
643 | |
644 | while (currentNewSample < maxValue || index < samples.size()) { |
645 | if (currentNewSample < samples.get(index).getValue()) { |
646 | if (newSamples.size() == 0) |
647 | newProb = (currentNewSample / samples.get(0).getValue()) |
648 | * samples.get(0).getProbability(); |
649 | else { |
650 | double dif = index == 0 ? samples.get(0).getValue() |
651 | : samples.get(index).getValue() |
652 | - samples.get(index - 1).getValue(); |
653 | newProb = (distance / dif) |
654 | * samples.get(index).getProbability(); |
655 | } |
656 | newSamples.add(newProb); |
657 | currentNewSample += distance; |
658 | |
659 | } else { |
660 | double fractionOfBox = 0; |
661 | if (index == 0) { |
662 | double totalXLengthOfBox = samples.get(index).getValue(); |
663 | double usedXLengthOfBox = samples.get(index).getValue() - currentNewSample + distance; |
664 | fractionOfBox = Math.min(1.0, usedXLengthOfBox / totalXLengthOfBox); |
665 | } else { |
666 | double totalXLengthOfBox = samples.get(index).getValue()- samples.get(index - 1).getValue(); |
667 | double usedXLengthOfBox = samples.get(index).getValue() - currentNewSample + distance; |
668 | fractionOfBox = usedXLengthOfBox / totalXLengthOfBox; |
669 | } |
670 | newProb = fractionOfBox * samples.get(index).getProbability(); |
671 | index++; |
672 | |
673 | while (index < samples.size() && samples.get(index).getValue() < currentNewSample) { |
674 | newProb += samples.get(index).getProbability(); |
675 | index++; |
676 | } |
677 | if (index < samples.size()) |
678 | newProb += (1 - ((samples.get(index).getValue() - currentNewSample) / (samples |
679 | .get(index).getValue() - samples.get(index - 1) |
680 | .getValue()))) |
681 | * samples.get(index).getProbability(); |
682 | newSamples.add(newProb); |
683 | currentNewSample += distance; |
684 | // if (currentNewSample > samples.get(index).getValue()) |
685 | // index++; |
686 | |
687 | } |
688 | } |
689 | return createSamplePDFFromDouble(distance, newSamples, false, bpdf |
690 | .getUnit()); |
691 | } |
692 | |
693 | private IBoxedPDF transformSampledToBoxedPDF(ISamplePDF spdf) |
694 | throws DoubleSampleException, FunctionNotInTimeDomainException { |
695 | if (spdf.isInFrequencyDomain()) |
696 | throw new FunctionNotInTimeDomainException(); |
697 | |
698 | List<Double> values = spdf.getValuesAsDouble(); |
699 | List<IContinuousSample> samples = new ArrayList<IContinuousSample>(); |
700 | |
701 | // int i = 1; |
702 | // for (Double d : values) { |
703 | // IContinuousSample sample = this.createContinuousSample(spdf |
704 | // .getDistance() |
705 | // * i, d); |
706 | // samples.add(sample); |
707 | // i++; |
708 | // } |
709 | double distance = spdf.getDistance(); |
710 | |
711 | for (int i = 0; i < values.size();) { |
712 | double currentProb = values.get(i); |
713 | double prob = currentProb; |
714 | for (i = i + 1; i < values.size(); i++) { |
715 | double nextProb = values.get(i); |
716 | if (MathTools.equalsDouble(nextProb, currentProb)) { |
717 | prob += nextProb; |
718 | } else { |
719 | break; |
720 | } |
721 | } |
722 | IContinuousSample s = this. |
723 | createContinuousSample(distance * i, prob); |
724 | samples.add(s); |
725 | } |
726 | |
727 | return createBoxedPDF(samples, spdf.getUnit()); |
728 | } |
729 | |
730 | |
731 | /** |
732 | * This function creates an approximation histogram of the passed pdf. |
733 | * The number of bins is fixed to 20. |
734 | * If the passed pdf has an infinite support (e.g. ranges from 0 to + |
735 | * infinity like the exponential function), the 95% or 5% percentile is |
736 | * used for the support of the histogram. |
737 | * The value of each bin with the range lowerLimit to upperLimit |
738 | * is the difference of the cumulated probabilities of its limit points: |
739 | * p(bin) = pdf.cdf(upperLimit) - pdf.cdf(lowerLimit). |
740 | * @param pdf The continuous probability function to approximate. |
741 | * @return |
742 | * @throws DoubleSampleException |
743 | */ |
744 | private IBoxedPDF transformContinuousToBoxedPDF(IContinousPDF pdf) throws DoubleSampleException { |
745 | // number of boxes needs to be defined. Not too much, or it becomes too big. |
746 | int numberOfBoxes = 20; |
747 | double cutMargin = 0.05; |
748 | |
749 | // get lower and upper bound for the boxes. |
750 | double xSup = pdf.getXsup(); |
751 | double xInf = pdf.getXinf(); |
752 | |
753 | // try xInf and xsup and test that not inifinity. If no, use them directly for bounds. |
754 | if (Double.isInfinite(xSup) || Double.isNaN(xSup)){ |
755 | // If yes, lets define it so that 95% of the |
756 | // probability is covered. |
757 | xSup = pdf.inverseF(1-cutMargin); |
758 | //TODO: adjust pdf to new xSup? |
759 | } |
760 | if (Double.isInfinite(xInf) || Double.isNaN(xInf)){ |
761 | xInf = pdf.inverseF(0+cutMargin); |
762 | //TODO: adjust pdf to new xInf? |
763 | } |
764 | |
765 | double stepwidth = (xSup - xInf) / 20; |
766 | double x = xInf; |
767 | double upperProbability = 0; |
768 | double lowerProbability = 0; |
769 | |
770 | List<IContinuousSample> samples = new ArrayList<IContinuousSample>(); |
771 | if (xInf != 0){ |
772 | IContinuousSample s = this.createContinuousSample(xInf, 0); |
773 | samples.add(s); |
774 | } |
775 | for (int i = 1; i <= numberOfBoxes; i++){ |
776 | x = xInf + i * stepwidth; |
777 | |
778 | lowerProbability = upperProbability; |
779 | upperProbability = pdf.cdf(x); |
780 | |
781 | IContinuousSample s = this.createContinuousSample(x, upperProbability - lowerProbability); |
782 | samples.add(s); |
783 | } |
784 | |
785 | BoxedPDFImpl boxedPdf = (BoxedPDFImpl)createBoxedPDF(samples, pdf.getUnit()); |
786 | double sum = boxedPdf.getProbabilitySum(); |
787 | |
788 | if (Math.abs(sum - 1) > 10e-10 ){ |
789 | // Adjust wrong PDFs |
790 | double delta = (1 - sum) / countNonZeroContiniousSamples(samples); |
791 | for(IContinuousSample sample : boxedPdf.getSamples()) { |
792 | if (sample.getProbability() > 0) |
793 | ((ContinuousSampleImpl)sample).setProbability(sample.getProbability()+delta); |
794 | } |
795 | } |
796 | |
797 | return boxedPdf; |
798 | } |
799 | |
800 | private double countNonZeroContiniousSamples(List<IContinuousSample> samples) { |
801 | int count=0; |
802 | for (IContinuousSample s : samples) |
803 | if (s.getProbability()>0) |
804 | count++; |
805 | return count; |
806 | } |
807 | |
808 | private List<Double> continuousSamplesToDoubles(List<IContinuousSample> list) { |
809 | ArrayList<Double> newList = new ArrayList<Double>(); |
810 | double start = 0; |
811 | for (IContinuousSample s : list) { |
812 | newList.add(s.getValue() - start); |
813 | start = s.getValue(); |
814 | } |
815 | return newList; |
816 | } |
817 | |
818 | public void setRandomGenerator(IRandomGenerator randomGenerator) { |
819 | this.randomGenerator = randomGenerator; |
820 | } |
821 | |
822 | @Override |
823 | public IRandomGenerator getRandomGenerator() { |
824 | |
825 | return this.randomGenerator; |
826 | } |
827 | |
828 | } |