1 | package de.uka.ipd.sdq.stoex.analyser.operations; |
2 | |
3 | import java.util.ArrayList; |
4 | import java.util.Collections; |
5 | import java.util.Comparator; |
6 | import java.util.Iterator; |
7 | import java.util.List; |
8 | |
9 | import de.uka.ipd.sdq.probfunction.math.IProbabilityDensityFunction; |
10 | import de.uka.ipd.sdq.probfunction.math.IProbabilityFunctionFactory; |
11 | import de.uka.ipd.sdq.probfunction.math.IProbabilityMassFunction; |
12 | import de.uka.ipd.sdq.probfunction.math.ISample; |
13 | import de.uka.ipd.sdq.probfunction.math.IUnit; |
14 | import de.uka.ipd.sdq.probfunction.math.exception.DifferentDomainsException; |
15 | import de.uka.ipd.sdq.probfunction.math.exception.DomainNotNumbersException; |
16 | import de.uka.ipd.sdq.probfunction.math.exception.FunctionsInDifferenDomainsException; |
17 | import de.uka.ipd.sdq.probfunction.math.exception.IncompatibleUnitsException; |
18 | import de.uka.ipd.sdq.probfunction.math.exception.UnknownPDFTypeException; |
19 | |
20 | /** |
21 | * An interface for term (+,-) and product (*,/,%) operations. |
22 | * @author koziolek |
23 | */ |
24 | public abstract class TermProductOperation { |
25 | |
26 | /** |
27 | * @author martens, Philipp Meier |
28 | */ |
29 | public IProbabilityMassFunction compute(IProbabilityMassFunction left, |
30 | IProbabilityMassFunction right) throws DifferentDomainsException { |
31 | |
32 | IUnit resultUnit = IProbabilityFunctionFactory.eINSTANCE |
33 | .createUnit(left.getUnit() + " * " + right.getUnit()); |
34 | boolean resultHasOrderedDomain = (left.hasOrderedDomain() && right |
35 | .hasOrderedDomain()); |
36 | |
37 | boolean isInteger = isIntegerSample(left) && isIntegerSample(right); |
38 | |
39 | // left and right are PMFs with samples nleft and nright |
40 | // generate a PMF with nleft*nright samples by |
41 | // multiplying both the probabilies and the values each |
42 | |
43 | List<ISample> resultList = new ArrayList<ISample>(); |
44 | |
45 | for (ISample sleft : left.getSamples()) { |
46 | for (ISample sright : right.getSamples()) { |
47 | if (isInteger) { |
48 | resultList |
49 | .add(IProbabilityFunctionFactory.eINSTANCE |
50 | .createSample(new Integer( |
51 | calculateOperationForValues( |
52 | getDoubleValue(sleft), |
53 | getDoubleValue(sright)) |
54 | .intValue()), sleft |
55 | .getProbability() |
56 | * sright.getProbability())); |
57 | } else { |
58 | resultList.add(IProbabilityFunctionFactory.eINSTANCE |
59 | .createSample(new Double( |
60 | calculateOperationForValues( |
61 | getDoubleValue(sleft), |
62 | getDoubleValue(sright))), sleft |
63 | .getProbability() |
64 | * sright.getProbability())); |
65 | } |
66 | } |
67 | } |
68 | |
69 | Collections.sort(resultList, new ValueBasedComparator()); |
70 | |
71 | // join two samples with the same value |
72 | Iterator<ISample> iterator = resultList.iterator(); |
73 | if (iterator.hasNext()){ |
74 | ISample previousSample = iterator.next(); |
75 | while (iterator.hasNext()) { |
76 | ISample iSample = iterator.next(); |
77 | |
78 | if (iSample.getValue().equals(previousSample.getValue())){ |
79 | iterator.remove(); |
80 | previousSample.setProbability(previousSample.getProbability()+iSample.getProbability()); |
81 | } else { |
82 | previousSample = iSample; |
83 | } |
84 | |
85 | } |
86 | } |
87 | |
88 | return IProbabilityFunctionFactory.eINSTANCE |
89 | .createProbabilityMassFunction(resultList, resultUnit, |
90 | resultHasOrderedDomain); |
91 | |
92 | } |
93 | |
94 | private boolean isIntegerSample(IProbabilityMassFunction function) { |
95 | boolean isInteger = true; |
96 | |
97 | for (ISample sample : function.getSamples()) { |
98 | if (!(sample.getValue() instanceof Integer)){ |
99 | isInteger = false; |
100 | break; |
101 | } |
102 | } |
103 | return isInteger; |
104 | } |
105 | |
106 | private Double getDoubleValue(ISample sample) { |
107 | if (sample.getValue() instanceof Number){ |
108 | return ((Number)sample.getValue()).doubleValue(); |
109 | } else { |
110 | return Double.NaN; |
111 | } |
112 | |
113 | } |
114 | |
115 | public abstract int compute(int left, int right); |
116 | |
117 | public abstract double compute(double left, double right); |
118 | |
119 | public abstract IProbabilityMassFunction compute(IProbabilityMassFunction left, |
120 | double right) throws DomainNotNumbersException; |
121 | |
122 | public IProbabilityDensityFunction compute( |
123 | IProbabilityDensityFunction leftPDF, |
124 | IProbabilityDensityFunction rightPDF) |
125 | throws FunctionsInDifferenDomainsException, |
126 | UnknownPDFTypeException, IncompatibleUnitsException { |
127 | |
128 | throw new UnsupportedOperationException("StoEx does not support calculation with two PDFs, like multiplying two PDFs. " + |
129 | "Check whether you actually mean to do this. " + |
130 | "The left PDF to calculate with is "+leftPDF.toString()+ |
131 | ", the right is "+rightPDF.toString()); |
132 | |
133 | } |
134 | |
135 | protected abstract Double calculateOperationForValues(Double value1, Double value2); |
136 | |
137 | public abstract IProbabilityDensityFunction compute( |
138 | IProbabilityDensityFunction left, double right) |
139 | throws DomainNotNumbersException; |
140 | |
141 | } |
142 | |
143 | class ValueBasedComparator implements Comparator<ISample> { |
144 | |
145 | @SuppressWarnings("unchecked") |
146 | public int compare(ISample arg0, ISample arg1) { |
147 | Object value0 = arg0.getValue(); |
148 | Object value1 = arg1.getValue(); |
149 | |
150 | if (value0.getClass().isInstance(value1)) { |
151 | return ((Comparable) value0).compareTo(value1); |
152 | } else if (value1.getClass().isInstance(value0)) { |
153 | int result = ((Comparable) value1).compareTo(value0); |
154 | return result * -1; |
155 | } else if (value1 instanceof Number && value0 instanceof Number) { |
156 | Number number0 = (Number) value0; |
157 | Number number1 = (Number) value1; |
158 | |
159 | return new Double(number0.doubleValue()).compareTo(new Double( |
160 | number1.doubleValue())); |
161 | } else { |
162 | throw new DifferentDomainsException(); |
163 | } |
164 | } |
165 | |
166 | } |