1 | package de.uka.ipd.sdq.reliability.solver.sensitivity; |
2 | |
3 | import java.util.ArrayList; |
4 | import java.util.List; |
5 | |
6 | import de.uka.ipd.sdq.pcmsolver.models.PCMInstance; |
7 | |
8 | /** |
9 | * Provides a possibility to define multiple sensitivity parameters to be |
10 | * defined within one sensitivity analysis. |
11 | * |
12 | * @author brosch |
13 | * |
14 | */ |
15 | public class MultiSensitivity extends MarkovSensitivity { |
16 | |
17 | /** |
18 | * Determines if all combinations of parameter values shall be examined. |
19 | */ |
20 | private boolean isCombinatory; |
21 | |
22 | /** |
23 | * List of sensitivity parameters. |
24 | */ |
25 | public List<MarkovSensitivity> sensitivityParameters; |
26 | |
27 | /** |
28 | * The constructor. |
29 | * |
30 | * @param name |
31 | * name of the sensitivity analysis |
32 | * @param sensitivityParameters |
33 | * list of sensitivity parameters |
34 | * @param isCombinatory |
35 | * indicates if all combinations of sensitivity parameters shall |
36 | * be examined |
37 | */ |
38 | public MultiSensitivity(final String name, |
39 | final List<MarkovSensitivity> sensitivityParameters, |
40 | final boolean isCombinatory) { |
41 | |
42 | // Initialize basic variables: |
43 | super(name, null); |
44 | |
45 | // Further initializations: |
46 | this.sensitivityParameters = sensitivityParameters; |
47 | this.isCombinatory = isCombinatory; |
48 | |
49 | // Determine the overall number of sensibility steps: |
50 | determineNumberOfSteps(); |
51 | } |
52 | |
53 | /** |
54 | * Alters the model according to the next sensitivity analysis step. |
55 | * |
56 | * @return indicates if the model could be successfully altered |
57 | */ |
58 | protected boolean alterModel() { |
59 | |
60 | // Control the model alteration proceeds as required: |
61 | boolean modelAltered = false; |
62 | |
63 | // In the non-combinatory case, let each sensitivity parameter alter the |
64 | // model: |
65 | if (!isCombinatory) { |
66 | for (MarkovSensitivity sensitivity : sensitivityParameters) { |
67 | if (sensitivity.alterModel() == true) { |
68 | modelAltered = true; |
69 | } |
70 | } |
71 | } |
72 | |
73 | // In the combinatory case, increase the overall step counter over all |
74 | // sensitivity parameters: |
75 | if (isCombinatory && (sensitivityParameters.size() > 0)) { |
76 | for (MarkovSensitivity sensitivity : sensitivityParameters) { |
77 | if (sensitivity.alterModel() == true) { |
78 | modelAltered = true; |
79 | } |
80 | } |
81 | } |
82 | |
83 | // Everything ok: |
84 | return modelAltered; |
85 | } |
86 | |
87 | /** |
88 | * Determines the overall number of sensitivity analysis steps. |
89 | */ |
90 | private void determineNumberOfSteps() { |
91 | numberOfSteps = (isCombinatory) ? 1 : 0; |
92 | for (MarkovSensitivity sensitivity : sensitivityParameters) { |
93 | if (!isCombinatory) { |
94 | if (sensitivity.numberOfSteps > numberOfSteps) { |
95 | numberOfSteps = sensitivity.numberOfSteps; |
96 | } |
97 | } else { |
98 | numberOfSteps *= sensitivity.numberOfSteps; |
99 | } |
100 | } |
101 | } |
102 | |
103 | /** |
104 | * Extracts the relevant sensitivity information from the given model. |
105 | */ |
106 | protected void extractSensitivityInformation() { |
107 | // Nothing to do in the MultiSensitivity. |
108 | } |
109 | |
110 | /** |
111 | * Retrieves the current step number. |
112 | * |
113 | * @return the current step number |
114 | */ |
115 | protected int getCurrentStepNumber() { |
116 | if (isCombinatory) { |
117 | int stepNumber = 1; |
118 | for (int i = 0; i < sensitivityParameters.size(); i++) { |
119 | int step = sensitivityParameters.get(i).getCurrentStepNumber(); |
120 | if (step == 0) { |
121 | return 0; |
122 | } |
123 | int weight = 1; |
124 | for (int j = i + 1; j < sensitivityParameters.size(); j++) { |
125 | weight *= sensitivityParameters.get(j).numberOfSteps; |
126 | } |
127 | stepNumber += weight * (step - 1); |
128 | } |
129 | return stepNumber; |
130 | } else { |
131 | int stepNumber = 0; |
132 | for (MarkovSensitivity sensitivity : sensitivityParameters) { |
133 | stepNumber = Math.max(stepNumber, sensitivity |
134 | .getCurrentStepNumber()); |
135 | } |
136 | return stepNumber; |
137 | } |
138 | } |
139 | |
140 | /** |
141 | * Builds the headings strings for logging. |
142 | * |
143 | * @return the log headings strings |
144 | */ |
145 | protected List<List<String>> getLogHeadingsMulti() { |
146 | |
147 | // Create a result list: |
148 | List<List<String>> resultList = new ArrayList<List<String>>(); |
149 | |
150 | // Build the lines of the result list: |
151 | ArrayList<String> newHeadings = new ArrayList<String>(); |
152 | ArrayList<List<List<String>>> existingHeadings = new ArrayList<List<List<String>>>(); |
153 | for (MarkovSensitivity sensitivity : sensitivityParameters) { |
154 | existingHeadings.add(sensitivity.getLogHeadingsMulti()); |
155 | } |
156 | resultList.add(newHeadings); |
157 | for (int i = 0; i < getMaxNumberOfLines(existingHeadings); i++) { |
158 | resultList.add(new ArrayList<String>()); |
159 | } |
160 | |
161 | // Fill the lines of the result list: |
162 | for (int i = 0; i < existingHeadings.size(); i++) { |
163 | int numberOfColums = 0; |
164 | for (int j = 0; j < existingHeadings.get(i).size(); j++) { |
165 | numberOfColums = existingHeadings.get(i).get(j).size(); |
166 | int resultIndex = resultList.size() |
167 | - existingHeadings.get(i).size() + j; |
168 | resultList.get(resultIndex).addAll( |
169 | existingHeadings.get(i).get(j)); |
170 | } |
171 | newHeadings.add(sensitivityParameters.get(i).name); |
172 | for (int j = 0; j < resultList.size() |
173 | - existingHeadings.get(i).size(); j++) { |
174 | for (int k = ((j == 0) ? 1 : 0); k < numberOfColums; k++) { |
175 | resultList.get(j).add(""); |
176 | } |
177 | } |
178 | } |
179 | |
180 | // Return the result: |
181 | return resultList; |
182 | } |
183 | |
184 | /** |
185 | * Builds the results strings for sensitivity logging. |
186 | * |
187 | * @return the results strings |
188 | */ |
189 | protected List<String> getLogSingleResultsMulti() { |
190 | |
191 | // Create a result list: |
192 | List<String> resultList = new ArrayList<String>(); |
193 | |
194 | // Create the result strings: |
195 | for (MarkovSensitivity sensitivity : sensitivityParameters) { |
196 | resultList.addAll(sensitivity.getLogSingleResultsMulti()); |
197 | } |
198 | |
199 | // Return the result: |
200 | return resultList; |
201 | } |
202 | |
203 | /** |
204 | * Determines the number of lines in the given list of log headings. |
205 | * |
206 | * @param logHeadingsList |
207 | * the list of log headings |
208 | * @return the number of lines |
209 | */ |
210 | private int getMaxNumberOfLines( |
211 | ArrayList<List<List<String>>> logHeadingsList) { |
212 | int maxNumberOfLines = 0; |
213 | for (int i = 0; i < logHeadingsList.size(); i++) { |
214 | int numberOfLines = logHeadingsList.get(i).size(); |
215 | maxNumberOfLines = Math.max(numberOfLines, maxNumberOfLines); |
216 | } |
217 | return maxNumberOfLines; |
218 | } |
219 | |
220 | /** |
221 | * Retrieves the current step count of a sensitivity parameter. |
222 | * |
223 | * @param index |
224 | * the index of the {@link SensitivityStatus} parameter |
225 | * @return the step count |
226 | */ |
227 | private int getStepCount(final int index) { |
228 | MarkovSensitivity sensitivity = sensitivityParameters.get(index); |
229 | return sensitivity.getCurrentStepNumber(); |
230 | } |
231 | |
232 | /** |
233 | * Increases the current step number. |
234 | * |
235 | * @return indicates an overflow |
236 | */ |
237 | protected boolean increaseCurrentStepNumber() { |
238 | if (isCombinatory) { |
239 | if (sensitivityParameters.size() > 0) { |
240 | return increaseStepCountRecursively(0); |
241 | } |
242 | return true; |
243 | } else { |
244 | boolean overflow = true; |
245 | for (MarkovSensitivity sensitivity : sensitivityParameters) { |
246 | if (!sensitivity.increaseCurrentStepNumber()) { |
247 | overflow = false; |
248 | } |
249 | } |
250 | return overflow; |
251 | } |
252 | } |
253 | |
254 | /** |
255 | * Increases the combinatory step count of a sensitivity parameter. |
256 | * |
257 | * @param index |
258 | * the index of sensitivity parameter |
259 | * @return true if an overflow happened |
260 | */ |
261 | private boolean increaseStepCount(final int index) { |
262 | MarkovSensitivity sensitivity = sensitivityParameters.get(index); |
263 | if (!sensitivity.increaseCurrentStepNumber()) { |
264 | for (int i = index + 1; i < sensitivityParameters.size(); i++) { |
265 | sensitivityParameters.get(i).resetCurrentStepNumber(); |
266 | } |
267 | return false; |
268 | } |
269 | return true; |
270 | } |
271 | |
272 | /** |
273 | * Increases the combinatory step count over all sensitivity parameters. |
274 | * |
275 | * @param index |
276 | * the index of the current sensitivity parameter |
277 | * @return true if an overflow happened |
278 | */ |
279 | private boolean increaseStepCountRecursively(final int index) { |
280 | |
281 | // Check for the cases of the recursion: |
282 | if (getStepCount(index) == 0) { |
283 | // Initial case, all step counts set to 1: |
284 | initStepCountRecusively(index); |
285 | return false; |
286 | } else if (sensitivityParameters.size() > index + 1) { |
287 | // Recursive case, increase counter: |
288 | if (increaseStepCountRecursively(index + 1)) { |
289 | return increaseStepCount(index); |
290 | } |
291 | return false; |
292 | } else { |
293 | // Base case, increase last counter: |
294 | return increaseStepCount(index); |
295 | } |
296 | } |
297 | |
298 | /** |
299 | * Initializes all sensitivity parameter step counts to 1. |
300 | * |
301 | * @param index |
302 | * the index of the current sensitivity parameter |
303 | */ |
304 | private void initStepCountRecusively(final int index) { |
305 | if (sensitivityParameters.size() > index) { |
306 | MarkovSensitivity sensitivity = sensitivityParameters.get(index); |
307 | sensitivity.resetCurrentStepNumber(); |
308 | initStepCountRecusively(index + 1); |
309 | } |
310 | } |
311 | |
312 | /** |
313 | * Resets the current step number. |
314 | * |
315 | */ |
316 | protected void resetCurrentStepNumber() { |
317 | for (MarkovSensitivity sensitivity : sensitivityParameters) { |
318 | sensitivity.resetCurrentStepNumber(); |
319 | } |
320 | } |
321 | |
322 | /** |
323 | * Sets the PCM instance. |
324 | * |
325 | * @param model |
326 | * the PCM instance |
327 | */ |
328 | protected void setModel(final PCMInstance model) { |
329 | super.setModel(model); |
330 | for (MarkovSensitivity sensitivity : sensitivityParameters) { |
331 | sensitivity.setModel(model); |
332 | } |
333 | } |
334 | } |