EMMA Coverage Report (generated Sun Feb 05 10:43:15 CET 2012)
[all classes][de.uka.ipd.sdq.reliability.solver.pcm2markov]

COVERAGE SUMMARY FOR SOURCE FILE [MarkovBuilder.java]

nameclass, %method, %block, %line, %
MarkovBuilder.java0%   (0/1)0%   (0/43)0%   (0/1959)0%   (0/431)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class MarkovBuilder0%   (0/1)0%   (0/43)0%   (0/1959)0%   (0/431)
MarkovBuilder (boolean): void 0%   (0/1)0%   (0/9)0%   (0/4)
addState (MarkovChain, StateType, String, List): State 0%   (0/1)0%   (0/28)0%   (0/6)
addStateForFailureDescription (MarkovChain, List, FailureDescription): State 0%   (0/1)0%   (0/57)0%   (0/13)
appendFailureHandlingChain (MarkovChain, MarkovChain, State, boolean): void 0%   (0/1)0%   (0/75)0%   (0/22)
appendFailureHandlingMarkovChain (MarkovChain, List, MarkovChain, List, boole... 0%   (0/1)0%   (0/27)0%   (0/7)
appendFailureHandlingMarkovChain (MarkovChain, MarkovChain, List, boolean): void 0%   (0/1)0%   (0/14)0%   (0/5)
appendFailureHandlingMarkovChains (MarkovChain, List, List, boolean): void 0%   (0/1)0%   (0/35)0%   (0/9)
connectStates (MarkovChain, State, State, double): void 0%   (0/1)0%   (0/22)0%   (0/7)
contributeTransition (MarkovChain, Transition): void 0%   (0/1)0%   (0/52)0%   (0/14)
copyMarkovChain (MarkovChain): MarkovChain 0%   (0/1)0%   (0/145)0%   (0/32)
delegateIncommingTransitions (MarkovChain, State, State): void 0%   (0/1)0%   (0/20)0%   (0/5)
delegateOutgoingTransitions (MarkovChain, State, State): void 0%   (0/1)0%   (0/20)0%   (0/5)
deleteTransitions (MarkovChain, ArrayList): void 0%   (0/1)0%   (0/16)0%   (0/3)
findFailureState (List, String): State 0%   (0/1)0%   (0/43)0%   (0/8)
findFailureStates (List, String): List 0%   (0/1)0%   (0/49)0%   (0/9)
findMatchingFailureState (List, State): State 0%   (0/1)0%   (0/9)0%   (0/2)
findMatchingFailureStates (List, State): List 0%   (0/1)0%   (0/9)0%   (0/2)
findStates (List, StateType): List 0%   (0/1)0%   (0/26)0%   (0/5)
findTransitionsFromState (MarkovChain, State): ArrayList 0%   (0/1)0%   (0/31)0%   (0/5)
findTransitionsToState (MarkovChain, State): ArrayList 0%   (0/1)0%   (0/31)0%   (0/5)
getFailureStates (MarkovChain): List 0%   (0/1)0%   (0/32)0%   (0/6)
getFailureTypeId (State): String 0%   (0/1)0%   (0/22)0%   (0/4)
getFailureTypeName (State): String 0%   (0/1)0%   (0/22)0%   (0/4)
getName (List): String 0%   (0/1)0%   (0/39)0%   (0/6)
getStartState (MarkovChain): State 0%   (0/1)0%   (0/29)0%   (0/5)
getStateName (String, List): String 0%   (0/1)0%   (0/22)0%   (0/3)
getStateTraces (String, List): List 0%   (0/1)0%   (0/17)0%   (0/5)
getSuccessState (MarkovChain): State 0%   (0/1)0%   (0/29)0%   (0/5)
incorporateMarkovChain (MarkovChain, MarkovChain, State, boolean, boolean): void 0%   (0/1)0%   (0/207)0%   (0/46)
indexOf (MarkovChain, State): int 0%   (0/1)0%   (0/22)0%   (0/4)
initBasicMarkovChain (List): MarkovChain 0%   (0/1)0%   (0/33)0%   (0/8)
initBasicMarkovChainWithFailures (List, List): MarkovChain 0%   (0/1)0%   (0/83)0%   (0/19)
initBehaviourMarkovChainByAction (List, List, List): MarkovChain 0%   (0/1)0%   (0/41)0%   (0/5)
initBranchMarkovChain (List, ArrayList): MarkovChain 0%   (0/1)0%   (0/77)0%   (0/15)
initForkMarkovChain (List, ArrayList, ArrayList): MarkovChain 0%   (0/1)0%   (0/32)0%   (0/4)
initLoopMarkovChain (List, ManagedPMF): MarkovChain 0%   (0/1)0%   (0/123)0%   (0/26)
initResourceFailureMarkovChain (List, List): MarkovChain 0%   (0/1)0%   (0/56)0%   (0/13)
initSequentialMarkovChain (List, List, List): MarkovChain 0%   (0/1)0%   (0/65)0%   (0/15)
isFailureTypeHandled (List, String): boolean 0%   (0/1)0%   (0/19)0%   (0/4)
nameTransition (Transition): void 0%   (0/1)0%   (0/17)0%   (0/3)
reduceState (MarkovChain, State): void 0%   (0/1)0%   (0/98)0%   (0/26)
removeDuplicateFailureStates (MarkovChain, boolean): void 0%   (0/1)0%   (0/75)0%   (0/16)
validateChain (MarkovChain): void 0%   (0/1)0%   (0/81)0%   (0/21)

1package de.uka.ipd.sdq.reliability.solver.pcm2markov;
2 
3import java.util.ArrayList;
4import java.util.List;
5 
6import de.uka.ipd.sdq.markov.Label;
7import de.uka.ipd.sdq.markov.MarkovChain;
8import de.uka.ipd.sdq.markov.MarkovFactory;
9import de.uka.ipd.sdq.markov.State;
10import de.uka.ipd.sdq.markov.StateType;
11import de.uka.ipd.sdq.markov.Transition;
12import de.uka.ipd.sdq.pcm.seff.AbstractAction;
13import de.uka.ipd.sdq.pcm.seff.ForkedBehaviour;
14import de.uka.ipd.sdq.probfunction.Sample;
15import de.uka.ipd.sdq.probfunction.math.ManagedPMF;
16 
17/**
18 * This class provides methods for building Markov Chains.
19 * 
20 * @author brosch
21 * 
22 */
23public class MarkovBuilder {
24 
25        /**
26         * Key to identify a Markov label as holding a failure type id.
27         */
28        private static final String FAILURETYPEID = "FailureTypeId";
29 
30        /**
31         * Key to identify a Markov label as holding a failure type name.
32         */
33        private static final String FAILURETYPENAME = "FailureTypeName";
34 
35        /**
36         * The Markov Factory is used to create the Elements of the Markov Chain
37         * Model resulting from the transformation.
38         */
39        private MarkovFactory markovFactory = MarkovFactory.eINSTANCE;
40 
41        /**
42         * Indicates if the resulting Makov model shall be augmented with tracing
43         * information for diagnostic purposes.
44         */
45        private boolean recordTraces;
46 
47        /**
48         * The constructor.
49         * 
50         * @param recordTraces
51         *            controls if traces shall be recorded during transformation
52         */
53        public MarkovBuilder(final boolean recordTraces) {
54                this.recordTraces = recordTraces;
55        }
56 
57        /**
58         * Adds a state of a given type and with a given name to a Markov chain.
59         * 
60         * @param chain
61         *            the Markov chain
62         * @param type
63         *            the type of state to add
64         * @param stateName
65         *            the name for the state to add
66         * @param prefixes
67         *            the prefixes to add to the state name
68         * @return the new state
69         */
70        private State addState(final MarkovChain chain, final StateType type,
71                        final String stateName, final List<String> prefixes) {
72                State state = markovFactory.createState();
73                state.setType(type);
74                state.setName(getStateName(stateName, prefixes));
75                state.getTraces().addAll(getStateTraces(stateName, prefixes));
76                chain.getStates().add(state);
77                return state;
78        }
79 
80        /**
81         * Adds a failure state to a given Markov chain.
82         * 
83         * @param chain
84         *            the Markov chain
85         * @param prefixes
86         *            the prefixes of the state name
87         * @param description
88         *            the description of the failure type
89         * @return the new failure state
90         */
91        private State addStateForFailureDescription(final MarkovChain chain,
92                        final List<String> prefixes, final FailureDescription description) {
93 
94                // Create the new failure state and add it to the chain:
95                State failureState = addState(chain, StateType.FAILURE,
96                                StateType.FAILURE.toString() + "("
97                                                + description.getFailureType().getName() + ")",
98                                prefixes);
99 
100                // Add a label to the state for the failure id:
101                Label failureIdLabel = markovFactory.createLabel();
102                failureIdLabel.setKey(FAILURETYPEID);
103                failureIdLabel.setValue(description.getFailureType().getId());
104                failureState.getLabels().add(failureIdLabel);
105 
106                // Add a label to the state for the failure name:
107                Label failureNameLabel = markovFactory.createLabel();
108                failureNameLabel.setKey(FAILURETYPENAME);
109                failureNameLabel.setValue(description.getFailureType().getName());
110                failureState.getLabels().add(failureNameLabel);
111 
112                // Return the new Failure state:
113                return failureState;
114        }
115 
116        /**
117         * Incorporates one Markov chain into another to replace a failure state
118         * with a new behavior.
119         * 
120         * @param aggregateChain
121         *            the outer Markov chain
122         * @param handlingChain
123         *            the inner Markov chain to replace the failure state
124         * @param failureState
125         *            the failure state to replace
126         * @param optimize
127         *            indicates if Markov Chain reduction shall be performed during
128         *            the transformation
129         */
130        private void appendFailureHandlingChain(final MarkovChain aggregateChain,
131                        final MarkovChain handlingChain, final State failureState,
132                        final boolean optimize) {
133 
134                // First validate both chains:
135                this.validateChain(aggregateChain);
136                this.validateChain(handlingChain);
137 
138                // Create a copy of the specific Markov Chain to prevent reuse of any
139                // States or Transitions of the specific Markov Chain within the
140                // aggregate Markov Chain (this could lead to problems when one specific
141                // Markov Chain is incorporated several times into the same aggregate
142                // Markov Chain):
143                MarkovChain handlingChainCopy = copyMarkovChain(handlingChain);
144 
145                // Find the relevant states:
146                State aggregateChainSuccessState = getSuccessState(aggregateChain);
147                List<State> aggregateChainFailureStates = getFailureStates(aggregateChain);
148 
149                State handlingChainStartState = getStartState(handlingChainCopy);
150                State handlingChainSuccessState = getSuccessState(handlingChainCopy);
151 
152                // Take over the specific Markov Chain into the aggregate Markov Chain:
153                aggregateChain.getStates().addAll(handlingChainCopy.getStates());
154                aggregateChain.getTransitions().addAll(
155                                handlingChainCopy.getTransitions());
156 
157                delegateIncommingTransitions(aggregateChain, failureState,
158                                handlingChainStartState);
159                handlingChainStartState.setType(StateType.DEFAULT);
160                aggregateChain.getStates().remove(failureState);
161                aggregateChainFailureStates.remove(failureState);
162 
163                connectStates(aggregateChain, handlingChainSuccessState,
164                                aggregateChainSuccessState, 1.0);
165                handlingChainSuccessState.setType(StateType.DEFAULT);
166 
167                // Optimize the aggregate MarkovChain:
168                if (optimize) {
169                        reduceState(aggregateChain, handlingChainStartState);
170                        reduceState(aggregateChain, handlingChainSuccessState);
171                }
172        }
173 
174        /**
175         * Incorporates one Markov Chain into another. The specific Markov Chain is
176         * inserted into the aggregate Markov Chain replacing the failure state.
177         * 
178         * @param aggregateChain
179         *            the Markov Chain which will incorporate the other chain
180         * @param aggregateFailureStates
181         *            the failure states of the aggregate chain that shall be
182         *            considered
183         * @param handlingChain
184         *            the Markov Chain which will be incorporated into the other
185         *            chain
186         * @param handledFailureTypeIds
187         *            the list of handled failure types
188         * @param removeDuplicateFailureStates
189         *            indicates if duplicateFailureStates shall be removed at the
190         *            end of the procedure
191         * @param optimize
192         *            indicates if Markov Chain reduction shall be performed during
193         *            the transformation
194         */
195        private void appendFailureHandlingMarkovChain(
196                        final MarkovChain aggregateChain,
197                        final List<State> aggregateFailureStates,
198                        final MarkovChain handlingChain,
199                        final List<String> handledFailureTypeIds, final boolean optimize) {
200                for (State failureState : aggregateFailureStates) {
201                        String failureTypeLabelValue = getFailureTypeId(failureState);
202                        if (isFailureTypeHandled(handledFailureTypeIds,
203                                        failureTypeLabelValue)) {
204                                appendFailureHandlingChain(aggregateChain, handlingChain,
205                                                failureState, optimize);
206                        }
207                }
208        }
209 
210        /**
211         * Incorporates one Markov Chain into another. The specific Markov Chain is
212         * inserted into the aggregate Markov Chain replacing the failure state.
213         * 
214         * @param aggregateChain
215         *            the Markov Chain which will incorporate the other chain
216         * @param handlingChain
217         *            the Markov Chain which will be incorporated into the other
218         *            chain
219         * @param handledFailureTypeIds
220         *            the list of handled failure types
221         * @param optimize
222         *            indicates if Markov Chain reduction shall be performed during
223         *            the transformation
224         */
225        public void appendFailureHandlingMarkovChain(
226                        final MarkovChain aggregateChain, final MarkovChain handlingChain,
227                        final List<String> handledFailureTypeIds, final boolean optimize) {
228                appendFailureHandlingMarkovChain(aggregateChain,
229                                getFailureStates(aggregateChain), handlingChain,
230                                handledFailureTypeIds, optimize);
231                removeDuplicateFailureStates(aggregateChain, optimize);
232        }
233 
234        /**
235         * Incorporates multiple Markov Chains into one aggregate chain. The
236         * specific Markov Chains are inserted into the aggregate Markov Chain
237         * replacing the failure states.
238         * 
239         * @param aggregateChain
240         *            the Markov Chain which will incorporate the other chains
241         * @param handlingChains
242         *            the Markov Chains which will be incorporated into the other
243         *            chain
244         * @param handledFailureTypeIdLists
245         *            the list of handled failure types per chain
246         * @param optimize
247         *            indicates if Markov Chain reduction shall be performed during
248         *            the transformation
249         */
250        public void appendFailureHandlingMarkovChains(
251                        final MarkovChain aggregateChain,
252                        final List<MarkovChain> handlingChains,
253                        final List<List<String>> handledFailureTypeIdLists,
254                        final boolean optimize) {
255                List<State> aggregateFailureStates = getFailureStates(aggregateChain);
256                for (int i = 0; i < handlingChains.size(); i++) {
257                        aggregateFailureStates = findStates(aggregateFailureStates,
258                                        StateType.FAILURE);
259                        appendFailureHandlingMarkovChain(aggregateChain,
260                                        aggregateFailureStates, handlingChains.get(i),
261                                        handledFailureTypeIdLists.get(i), optimize);
262                }
263                removeDuplicateFailureStates(aggregateChain, optimize);
264        }
265 
266        /**
267         * Adds a new transition to a given Markov chain.
268         * 
269         * @param chain
270         *            the Markov chain
271         * @param from
272         *            the source state
273         * @param to
274         *            the target state
275         * @param probability
276         *            the probability to annotate the new transition
277         */
278        private void connectStates(final MarkovChain chain, final State from,
279                        final State to, final double probability) {
280                Transition transition = markovFactory.createTransition();
281                transition.setFromState(from);
282                transition.setToState(to);
283                transition.setProbability(probability);
284                nameTransition(transition);
285                chain.getTransitions().add(transition);
286        }
287 
288        /**
289         * Adds the given Transition to the given Markov Chain. If the given Markov
290         * Chain already has a Transition between the same source and target States,
291         * the already existing Transition is merged with the new one by summing up
292         * the probabilities of the two Transitions.
293         * 
294         * @param markovChain
295         *            the Markov Chain
296         * @param transitionToContribute
297         *            the Transition
298         */
299        private void contributeTransition(final MarkovChain markovChain,
300                        final Transition transitionToContribute) {
301 
302                // Go through the Transitions of the Markov Chain to find an already
303                // existing Transition that corresponds to the new one:
304                Transition transitionCorresponding = null;
305                for (int i = 0; i < markovChain.getTransitions().size(); i++) {
306                        if ((markovChain.getTransitions().get(i).getFromState() == transitionToContribute
307                                        .getFromState())
308                                        && (markovChain.getTransitions().get(i).getToState() == transitionToContribute
309                                                        .getToState())) {
310                                transitionCorresponding = markovChain.getTransitions().get(i);
311                                break;
312                        }
313                }
314 
315                // Does a corresponding Transition already exist?
316                if (transitionCorresponding != null) {
317 
318                        // Add the probability of the new Transition to that of the already
319                        // existing one:
320                        transitionCorresponding.setProbability(transitionCorresponding
321                                        .getProbability()
322                                        + transitionToContribute.getProbability());
323                } else {
324 
325                        // Simply add the new Transition to the Markov Chain:
326                        markovChain.getTransitions().add(transitionToContribute);
327                }
328        }
329 
330        /**
331         * Creates a copy of a Markov Chain. All States and Transitions of the
332         * original Markov Chain are copied into the new one.
333         * 
334         * @param originalMarkovChain
335         *            the original Markov Chain
336         * @return the new Markov Chain
337         */
338        public MarkovChain copyMarkovChain(final MarkovChain originalMarkovChain) {
339 
340                // Create a new Markov Chain instance:
341                MarkovChain newMarkovChain = markovFactory.createMarkovChain();
342                newMarkovChain.setName(originalMarkovChain.getName());
343 
344                // Copy all States from the original Markov Chain into the new one:
345                for (int i = 0; i < originalMarkovChain.getStates().size(); i++) {
346 
347                        State originalState = originalMarkovChain.getStates().get(i);
348                        // Create a new Markov State:
349                        State newState = markovFactory.createState();
350                        newState.setName(originalState.getName());
351                        newState.setType(originalState.getType());
352 
353                        for (Label originalLabel : originalState.getLabels()) {
354                                Label newLabel = markovFactory.createLabel();
355                                newLabel.setKey(originalLabel.getKey());
356                                newLabel.setValue(originalLabel.getValue());
357                                newState.getLabels().add(newLabel);
358                        }
359 
360                        // Add Traces information:
361                        newState.getTraces().addAll(originalState.getTraces());
362 
363                        // Add the new State to the new Markov Chain:
364                        newMarkovChain.getStates().add(newState);
365                }
366 
367                // Copy all Transitions from the originial Markov Chain into the new
368                // one:
369                for (int i = 0; i < originalMarkovChain.getTransitions().size(); i++) {
370 
371                        // Create a new Transition:
372                        Transition newTransition = markovFactory.createTransition();
373                        newTransition.setName(originalMarkovChain.getTransitions().get(i)
374                                        .getName());
375                        newTransition.setProbability(originalMarkovChain.getTransitions()
376                                        .get(i).getProbability());
377 
378                        // Determine the source and target States of the new Transition:
379                        State fromState = newMarkovChain.getStates().get(
380                                        originalMarkovChain.getStates().indexOf(
381                                                        originalMarkovChain.getTransitions().get(i)
382                                                                        .getFromState()));
383                        State toState = newMarkovChain.getStates().get(
384                                        originalMarkovChain.getStates().indexOf(
385                                                        originalMarkovChain.getTransitions().get(i)
386                                                                        .getToState()));
387                        newTransition.setFromState(fromState);
388                        newTransition.setToState(toState);
389 
390                        // Add the new Transition to the new Markov Chain:
391                        newMarkovChain.getTransitions().add(newTransition);
392                }
393 
394                // Return the resulting Markov Chain:
395                return newMarkovChain;
396        }
397 
398        /**
399         * Delegates incoming transitions from an original state to a new state.
400         * 
401         * @param chain
402         *            the Markov chain
403         * @param originalState
404         *            the original state
405         * @param newState
406         *            the new state
407         */
408        private void delegateIncommingTransitions(final MarkovChain chain,
409                        final State originalState, final State newState) {
410                ArrayList<Transition> transitions = findTransitionsToState(chain,
411                                originalState);
412                for (Transition transition : transitions) {
413                        transition.setToState(newState);
414                }
415        }
416 
417        /**
418         * Delegates outgoing transitions from an original state to a new state.
419         * 
420         * @param chain
421         *            the Markov chain
422         * @param originalState
423         *            the original state
424         * @param newState
425         *            the new state
426         */
427        private void delegateOutgoingTransitions(final MarkovChain chain,
428                        final State originalState, final State newState) {
429                ArrayList<Transition> transitions = findTransitionsFromState(chain,
430                                originalState);
431                for (Transition transition : transitions) {
432                        transition.setFromState(newState);
433                }
434        }
435 
436        /**
437         * Deletes all Transitions from the given Markov Model which are part of the
438         * given transitions list.
439         * 
440         * @param markovChain
441         *            the Markov Chain
442         * @param transitionsToDelete
443         *            the transition list
444         */
445        private void deleteTransitions(final MarkovChain markovChain,
446                        final ArrayList<Transition> transitionsToDelete) {
447 
448                // Go through all transitions of the given list:
449                for (int i = 0; i < transitionsToDelete.size(); i++) {
450 
451                        // Remove this transition from the Markov Chain:
452                        markovChain.getTransitions().remove(transitionsToDelete.get(i));
453                }
454        }
455 
456        /**
457         * Finds a failure state out of a given list of states.
458         * 
459         * @param states
460         *            the list of states
461         * @param failureTypeLabelValue
462         *            the type of failure state to find
463         * @return the failure state; NULL if no corresponding failure state could
464         *         be found
465         */
466        private State findFailureState(final List<State> states,
467                        final String failureTypeLabelValue) {
468                for (State state : states) {
469                        if (!state.getType().equals(StateType.FAILURE)) {
470                                continue;
471                        }
472                        for (Label label : state.getLabels()) {
473                                // TODO: this is linear search inside an outer loop! improve
474                                // performance
475                                if ((label.getKey().equals(FAILURETYPEID))
476                                                && (label.getValue().equals(failureTypeLabelValue))) {
477                                        return state;
478                                }
479                        }
480                }
481                return null;
482        }
483 
484        /**
485         * Finds the failure states out of a given list of states.
486         * 
487         * @param states
488         *            the list of states
489         * @param failureTypeLabelValue
490         *            the type of failure state to find
491         * @return the failure states; NULL if no corresponding failure state could
492         *         be found
493         */
494        private List<State> findFailureStates(final List<State> states,
495                        final String failureTypeLabelValue) {
496                List<State> resultList = new ArrayList<State>();
497                for (State state : states) {
498                        if (!state.getType().equals(StateType.FAILURE)) {
499                                continue;
500                        }
501                        for (Label label : state.getLabels()) {
502                                // TODO: this is linear search inside an outer loop! improve
503                                // performance
504                                if ((label.getKey().equals(FAILURETYPEID))
505                                                && (label.getValue().equals(failureTypeLabelValue))) {
506                                        resultList.add(state);
507                                }
508                        }
509                }
510                return resultList;
511        }
512 
513        /**
514         * Finds a failure state out of a given list of states.
515         * 
516         * @param states
517         *            the list of states
518         * @param failureState
519         *            the failure state to match
520         * @return the failure state; NULL if no corresponding failure state could
521         *         be found
522         */
523        private State findMatchingFailureState(final List<State> states,
524                        final State failureState) {
525                String failureTypeLabelValue = getFailureTypeId(failureState);
526                return findFailureState(states, failureTypeLabelValue);
527        }
528 
529        /**
530         * Finds the failure states out of a given list of states.
531         * 
532         * @param states
533         *            the list of states
534         * @param failureState
535         *            the failure state to match
536         * @return the failure states
537         */
538        private List<State> findMatchingFailureStates(final List<State> states,
539                        final State failureState) {
540                String failureTypeLabelValue = getFailureTypeId(failureState);
541                return findFailureStates(states, failureTypeLabelValue);
542        }
543 
544        /**
545         * Retrieves all Markov states of a given type from a given state list.
546         * 
547         * @param states
548         *            the list of states to search through
549         * @param type
550         *            the requested state type
551         * @return the sub list if states of the requested type
552         */
553        private List<State> findStates(final List<State> states,
554                        final StateType type) {
555                List<State> resultList = new ArrayList<State>();
556                for (State state : states) {
557                        if (state.getType().equals(type)) {
558                                resultList.add(state);
559                        }
560                }
561                return resultList;
562        }
563 
564        /**
565         * Creates a list of all Transitions in a Markov Chain that start from a
566         * given source state.
567         * 
568         * @param markovChain
569         *            the Markov Chain
570         * @param sourceState
571         *            the source state
572         * @return the list of transitions
573         */
574        private ArrayList<Transition> findTransitionsFromState(
575                        final MarkovChain markovChain, final State sourceState) {
576 
577                // Initialize the resulting List:
578                ArrayList<Transition> resultList = new ArrayList<Transition>();
579 
580                // Go through all transitions of the Markov Chain:
581                for (int i = 0; i < markovChain.getTransitions().size(); i++) {
582                        if (markovChain.getTransitions().get(i).getFromState() == sourceState) {
583                                resultList.add(markovChain.getTransitions().get(i));
584                        }
585                }
586 
587                // Return the result:
588                return resultList;
589        }
590 
591        /**
592         * Creates a list of all Transitions in a Markov Chain that lead to a given
593         * target state.
594         * 
595         * @param markovChain
596         *            the Markov Chain
597         * @param targetState
598         *            the target state
599         * @return the list of transitions
600         */
601        private ArrayList<Transition> findTransitionsToState(
602                        final MarkovChain markovChain, final State targetState) {
603 
604                // Initialize the resulting List:
605                ArrayList<Transition> resultList = new ArrayList<Transition>();
606 
607                // Go through all transitions of the Markov Chain:
608                for (int i = 0; i < markovChain.getTransitions().size(); i++) {
609                        if (markovChain.getTransitions().get(i).getToState() == targetState) {
610                                resultList.add(markovChain.getTransitions().get(i));
611                        }
612                }
613 
614                // Return the result:
615                return resultList;
616        }
617 
618        /**
619         * Gets all failure states out of a given Markov chain.
620         * 
621         * @param markovChain
622         *            the Markov chain
623         * @return the list of failure states
624         */
625        public List<State> getFailureStates(final MarkovChain markovChain) {
626 
627                // Initialize the resulting list:
628                List<State> failureStates = new ArrayList<State>();
629 
630                // Go through all states of the Markov Chain:
631                for (int i = 0; i < markovChain.getStates().size(); i++) {
632                        if (markovChain.getStates().get(i).getType().equals(
633                                        StateType.FAILURE)) {
634                                failureStates.add(markovChain.getStates().get(i));
635                        }
636                }
637 
638                // Return the result:
639                return failureStates;
640        }
641 
642        /**
643         * Gets the failure type annotation of a Markov failure state.
644         * 
645         * @param state
646         *            the state to examine
647         * @return the failure type annotation of the state
648         */
649        public String getFailureTypeId(final State state) {
650                for (Label label : state.getLabels()) {
651                        if (label.getKey().equals(FAILURETYPEID)) {
652                                return label.getValue();
653                        }
654                }
655                return null;
656        }
657 
658        /**
659         * Gets the failure type annotation of a Markov failure state.
660         * 
661         * @param state
662         *            the state to examine
663         * @return the failure type annotation of the state
664         */
665        public String getFailureTypeName(final State state) {
666                for (Label label : state.getLabels()) {
667                        if (label.getKey().equals(FAILURETYPENAME)) {
668                                return label.getValue();
669                        }
670                }
671                return null;
672        }
673 
674        /**
675         * Retrieves a name from a given list of prefixes.
676         * 
677         * @param prefixes
678         *            the list of prefixes
679         * @return the resulting name
680         */
681        private String getName(final List<String> prefixes) {
682                String result = "";
683                for (int i = 0; i < prefixes.size(); i++) {
684                        result += prefixes.get(i);
685                        if (i < prefixes.size() - 1) {
686                                result += "::";
687                        }
688                }
689                return result;
690        }
691 
692        /**
693         * Gets the start state out of a given Markov chain.
694         * 
695         * @param markovChain
696         *            the Markov chain
697         * @return the start state
698         */
699        public State getStartState(final MarkovChain markovChain) {
700 
701                // Go through all states of the Markov Chain:
702                for (int i = 0; i < markovChain.getStates().size(); i++) {
703                        if (markovChain.getStates().get(i).getType()
704                                        .equals(StateType.START)) {
705                                return markovChain.getStates().get(i);
706                        }
707                }
708 
709                // No start state found:
710                throw new MarkovException("Markov Chain has no start state.");
711        }
712 
713        /**
714         * Determines the composed name of a Markov state.
715         * 
716         * @param stateName
717         *            the state name
718         * @param prefixes
719         *            the prefixes of the state name
720         * @return the composed name
721         */
722        private String getStateName(final String stateName,
723                        final List<String> prefixes) {
724                if (prefixes.isEmpty()) {
725                        return stateName;
726                } else {
727                        return prefixes.get(prefixes.size() - 1) + "::" + stateName;
728                }
729        }
730 
731        /**
732         * Determines the traces of a Markov state.
733         * 
734         * @param stateName
735         *            the state name
736         * @param prefixes
737         *            the prefixes of the state name
738         * @return the trace list of the state
739         */
740        private List<String> getStateTraces(final String stateName,
741                        final List<String> prefixes) {
742                ArrayList<String> resultList = new ArrayList<String>();
743                if (recordTraces) {
744                        resultList.addAll(prefixes);
745                        resultList.add(stateName);
746                }
747                return resultList;
748        }
749 
750        /**
751         * Gets the success state out of a given Markov chain.
752         * 
753         * @param markovChain
754         *            the Markov Chain
755         * @return the Success State
756         */
757        public State getSuccessState(final MarkovChain markovChain) {
758 
759                // Go through all states of the Markov Chain:
760                for (int i = 0; i < markovChain.getStates().size(); i++) {
761                        if (markovChain.getStates().get(i).getType().equals(
762                                        StateType.SUCCESS)) {
763                                return markovChain.getStates().get(i);
764                        }
765                }
766 
767                // No success state found:
768                throw new MarkovException("Markov Chain has no success state.");
769        }
770 
771        /**
772         * Incorporates one Markov Chain into another. The specific Markov Chain is
773         * inserted into the aggregate Markov Chain replacing the given aggregate
774         * Markov State.
775         * 
776         * @param parentChain
777         *            the Markov Chain which will incorporate the other chain
778         * @param specificMarkovChain
779         *            the Markov Chain which will be incorporated into the other
780         *            chain
781         * @param aggregateState
782         *            the Markov State in the aggregate Markov Chain which will be
783         *            replaced by the specific Markov Chain
784         * @param optimize
785         *            indicates if Markov Chain reduction shall be performed during
786         *            the transformation
787         * @param appendPrefixes
788         *            indicates if prefixes of specific chain shall be appended to
789         *            prefixes of aggregateChain
790         */
791        public void incorporateMarkovChain(final MarkovChain parentChain,
792                        final MarkovChain specificMarkovChain, final State aggregateState,
793                        final boolean optimize, final boolean appendPrefixes) {
794 
795                // Assure that the replaceable Markov State is contained in the
796                // aggregate Markov Chain:
797                if (!parentChain.getStates().contains(aggregateState)) {
798                        throw new MarkovException("State '" + aggregateState
799                                        + "' is not contained in the markov chain '"
800                                        + parentChain.getName() + "'.");
801                }
802 
803                // Assure that the replaceable Markov State is not a Start, Success or
804                // Failure State:
805                if (!aggregateState.getType().equals(StateType.DEFAULT)) {
806                        throw new MarkovException(
807                                        "Only default states can be incorporated. '"
808                                                        + aggregateState.getName() + "' is of type '"
809                                                        + aggregateState.getType() + "'.");
810                }
811 
812                // Create a copy of the specific Markov Chain to prevent reuse of any
813                // States or Transitions of the specific Markov Chain within the
814                // aggregate Markov Chain (this could lead to problems when one specific
815                // Markov Chain is incorporated several times into the same aggregate
816                // Markov Chain):
817                MarkovChain copiedSpecificMarkovChain = copyMarkovChain(specificMarkovChain);
818 
819                // Find the Start, Success and Failure States of the aggregate Markov
820                // Chain:
821                List<State> stateAggregateFailures = getFailureStates(parentChain);
822 
823                // Find the Start, Success and Failure States of the specific Markov
824                // Chain:
825                State stateSpecificStart = getStartState(copiedSpecificMarkovChain);
826                State stateSpecificSuccess = getSuccessState(copiedSpecificMarkovChain);
827                List<State> stateSpecificFailures = getFailureStates(copiedSpecificMarkovChain);
828 
829                // Augment specific Makov traces with the aggregate state trace:
830                if (recordTraces && appendPrefixes) {
831                        for (State specificState : copiedSpecificMarkovChain.getStates()) {
832                                specificState.getTraces().addAll(0, aggregateState.getTraces());
833                                specificState.setName(getStateName(specificState.getTraces()
834                                                .get(specificState.getTraces().size() - 1),
835                                                specificState.getTraces().subList(0,
836                                                                specificState.getTraces().size() - 1)));
837                        }
838                }
839 
840                // Take over the specific Markov Chain into the aggregate Markov Chain:
841                parentChain.getStates().addAll(copiedSpecificMarkovChain.getStates());
842                parentChain.getTransitions().addAll(
843                                copiedSpecificMarkovChain.getTransitions());
844 
845                // all transitions to the replaceable state are delegated to the inner
846                // start state
847                delegateIncommingTransitions(parentChain, aggregateState,
848                                stateSpecificStart);
849                stateSpecificStart.setType(StateType.DEFAULT);
850 
851                // absorb failure states. for already existing failure type states
852                // delegate transitions
853                // from inner duplicates.
854                List<State> duplicateFailureStates = new ArrayList<State>();
855                for (State failureState : stateSpecificFailures) {
856                        // check if this is a duplicate
857                        State existingFailureState = findMatchingFailureState(
858                                        stateAggregateFailures, failureState);
859                        if (existingFailureState != null) { // duplicate found
860                                // delegate from duplicate to existing state
861                                connectStates(parentChain, failureState, existingFailureState,
862                                                1.0);
863                                // remove duplicate
864                                failureState.setType(StateType.DEFAULT);
865                                duplicateFailureStates.add(failureState);
866                        }
867                }
868 
869                //
870                delegateOutgoingTransitions(parentChain, aggregateState,
871                                stateSpecificSuccess);
872                stateSpecificSuccess.setType(StateType.DEFAULT);
873 
874                // remove the
875                parentChain.getStates().remove(aggregateState);
876 
877                // Optimize the aggregate MarkovChain:
878                if (optimize) {
879                        reduceState(parentChain, stateSpecificStart);
880                        reduceState(parentChain, stateSpecificSuccess);
881                        for (State failureState : duplicateFailureStates) {
882                                reduceState(parentChain, failureState);
883                        }
884                }
885        }
886 
887        /**
888         * Retrieves the index of a given State within a given Markov Chain.
889         * 
890         * @param markovChain
891         *            the Markov Chain
892         * @param state
893         *            the state to find
894         * @return the required index
895         */
896        public int indexOf(final MarkovChain markovChain, final State state) {
897 
898                // Go through all states of the Markov Chain:
899                for (int i = 0; i < markovChain.getStates().size(); i++) {
900                        if (markovChain.getStates().get(i) == state) {
901                                return i;
902                        }
903                }
904 
905                // Nothing found?
906                throw new MarkovException("State not found in Markov chain.");
907        }
908 
909        /**
910         * Initializes a new Markov Chain. The new Markov Chain has only three
911         * states: a start state, a success state and a failure state. A single
912         * transition goes from start to success with probability 1.
913         * 
914         * @param prefixes
915         *            the prefixes of the chain name
916         * @return the new Markov Chain
917         */
918        public MarkovChain initBasicMarkovChain(final List<String> prefixes) {
919 
920                // Create the Markov Chain Entity:
921                MarkovChain markovChain = markovFactory.createMarkovChain();
922                markovChain.setName(getName(prefixes));
923 
924                // Create the Start and Success States:
925                State startState = addState(markovChain, StateType.START,
926                                StateType.START.toString(), prefixes);
927                State successSate = addState(markovChain, StateType.SUCCESS,
928                                StateType.SUCCESS.toString(), prefixes);
929                connectStates(markovChain, startState, successSate, 1.0);
930 
931                // Return the result:
932                return markovChain;
933        }
934 
935        /**
936         * Creates a basic Markov chain with a start, success and multiple failure
937         * nodes for a given list of failure descriptions. Such a chain can be used
938         * to represent an internal action with its application failure
939         * probabilities, or the sending of a message over a communication link. All
940         * failure probabilities must sum up to at most 1.0.
941         * 
942         * @param prefixes
943         *            the prefixes of the chain name
944         * @param failureDescriptions
945         *            a list of failure descriptions
946         * @return the resulting Markov Chain
947         */
948        public MarkovChain initBasicMarkovChainWithFailures(
949                        final List<String> prefixes,
950                        final List<FailureDescription> failureDescriptions) {
951 
952                // Create the Markov Chain Entity:
953                MarkovChain markovChain = markovFactory.createMarkovChain();
954                markovChain.setName(getName(prefixes));
955 
956                // Create the Start and Success States:
957                State startState = addState(markovChain, StateType.START,
958                                StateType.START.toString(), prefixes);
959                State successState = addState(markovChain, StateType.SUCCESS,
960                                StateType.SUCCESS.toString(), prefixes);
961 
962                // Start with the assumption of total reliability:
963                double successProbability = 1.0;
964 
965                // Create failure states and connecting transitions:
966                for (FailureDescription description : failureDescriptions) {
967                        State failureState = addStateForFailureDescription(markovChain,
968                                        prefixes, description);
969                        connectStates(markovChain, startState, failureState, description
970                                        .getFailureProbability());
971                        successProbability -= description.getFailureProbability();
972                }
973 
974                // Assure that the reliability has not decreased below zero:
975                if (successProbability < 0) {
976                        throw new MarkovException(
977                                        "Total failure probability of basic Chain \""
978                                                        + getName(prefixes) + "\" is greater than 1.0.");
979                }
980 
981                // Create the Transition from Start State to Success State:
982                connectStates(markovChain, startState, successState, successProbability);
983 
984                // Return the result:
985                return markovChain;
986        }
987 
988        /**
989         * Creates a Markov Chain that represents an execution of a
990         * ScenarioBehaviour or ResourceDemandingBehaviour.
991         * 
992         * @param prefixes
993         *            the prefixes of the Markov Chain name
994         * @param actions
995         *            the actions of the Behaviour
996         * @param statesOut
997         *            the list of states created within the method that corresponds
998         *            to the given list of actions
999         * @return the resulting Markov Chain
1000         */
1001        public MarkovChain initBehaviourMarkovChainByAction(
1002                        final List<String> prefixes, final List<AbstractAction> actions,
1003                        final List<State> statesOut) {
1004 
1005                // Collect the action names:
1006                ArrayList<String> actionNames = new ArrayList<String>();
1007                for (int i = 0; i < actions.size(); i++) {
1008                        actionNames.add(actions.get(i).getEntityName() + "["
1009                                        + actions.get(i).getId() + "]");
1010                }
1011 
1012                // Build the Markov Chain:
1013                return initSequentialMarkovChain(prefixes, actionNames, statesOut);
1014        }
1015 
1016        /**
1017         * Creates a Markov Chain for a branch with solved branch probabilities.
1018         * 
1019         * @param prefixes
1020         *            the prefixes of the branch name
1021         * @param branchProbabilities
1022         *            the branch probabilities
1023         * @return the resulting Markov Chain
1024         */
1025        public MarkovChain initBranchMarkovChain(final List<String> prefixes,
1026                        final ArrayList<Double> branchProbabilities) {
1027 
1028                // Create the Markov Chain Entity:
1029                MarkovChain markovChain = markovFactory.createMarkovChain();
1030                markovChain.setName(getName(prefixes));
1031 
1032                // Create the Start and Success States:
1033                State startState = addState(markovChain, StateType.START,
1034                                StateType.START.toString(), prefixes);
1035                State successState = addState(markovChain, StateType.SUCCESS,
1036                                StateType.SUCCESS.toString(), prefixes);
1037 
1038                // Go through the given branch probabilities:
1039                for (int i = 0; i < branchProbabilities.size(); i++) {
1040 
1041                        // Check for a positive branch probability:
1042                        if (branchProbabilities.get(i) <= 0.0) {
1043                                continue;
1044                        }
1045 
1046                        // Create a new State:
1047                        State stateBranch = addState(markovChain, StateType.DEFAULT,
1048                                        "Alternative(" + (i + 1) + ")", prefixes);
1049 
1050                        // Create a transition from the Start State to the new one:
1051                        connectStates(markovChain, startState, stateBranch,
1052                                        branchProbabilities.get(i));
1053 
1054                        // Create a transition from new state to the success state
1055                        connectStates(markovChain, stateBranch, successState, 1.0);
1056                }
1057 
1058                // Return the result:
1059                return markovChain;
1060        }
1061 
1062        /**
1063         * Creates a Markov Chain for a fork action with a list of forked
1064         * behaviours.
1065         * 
1066         * @param prefixes
1067         *            the prefixes of the fork name
1068         * @param behaviours
1069         *            the list of forked behaviours
1070         * @param statesOut
1071         *            the list of states created within the method
1072         * @return the resulting Markov chain
1073         */
1074        public MarkovChain initForkMarkovChain(List<String> prefixes,
1075                        ArrayList<ForkedBehaviour> behaviours, ArrayList<State> statesOut) {
1076 
1077                // Collect the action names:
1078                ArrayList<String> behaviourNames = new ArrayList<String>();
1079                for (int i = 0; i < behaviours.size(); i++) {
1080                        behaviourNames.add("ForkBehaviour(" + (i + 1) + ")");
1081                }
1082 
1083                // Build the Markov Chain:
1084                return initSequentialMarkovChain(prefixes, behaviourNames, statesOut);
1085        }
1086 
1087        /**
1088         * Creates a Markov Chain for a loop with solved probability mass function.
1089         * 
1090         * @param prefixes
1091         *            the prefixes of the loop name
1092         * @param pmf
1093         *            the probability mass function of the loop
1094         * @return the resulting Markov Chain
1095         */
1096        public MarkovChain initLoopMarkovChain(final List<String> prefixes,
1097                        final ManagedPMF pmf) {
1098 
1099                // Create the Markov Chain Entity:
1100                MarkovChain markovChain = markovFactory.createMarkovChain();
1101                markovChain.setName(getName(prefixes));
1102 
1103                // Create the Start and Success States:
1104                State startState = addState(markovChain, StateType.START,
1105                                StateType.START.toString(), prefixes);
1106                State successState = addState(markovChain, StateType.SUCCESS,
1107                                StateType.SUCCESS.toString(), prefixes);
1108 
1109                // Go through the samples of the probability mass function:
1110                for (int i = 0; i < pmf.getModelPmf().getSamples().size(); i++) {
1111                        Sample sample = pmf.getModelPmf().getSamples().get(i);
1112                        if (!(sample.getValue() instanceof Integer)) {
1113                                throw new MarkovException("Invalid Sample value "
1114                                                + sample.getValue().toString() + " in "
1115                                                + pmf.getModelPmf().toString());
1116                        }
1117 
1118                        int sampleValue = (Integer) sample.getValue();
1119 
1120                        // Mark the State that will lead to the Success State:
1121                        State stateToSuccess = startState;
1122                        double transitionProbability = sample.getProbability();
1123 
1124                        // Go through the iterations of this sample:
1125                        for (int j = 0; j < sampleValue; j++) {
1126 
1127                                // Create a new State:
1128                                State stateSample = addState(markovChain, StateType.DEFAULT,
1129                                                "Alternative(" + (i + 1) + ")-Iteration(" + (j + 1)
1130                                                                + ")", prefixes);
1131                                connectStates(markovChain, stateToSuccess, stateSample,
1132                                                transitionProbability);
1133 
1134                                // Update State and probability:
1135                                stateToSuccess = stateSample;
1136                                transitionProbability = 1;
1137                        }
1138 
1139                        connectStates(markovChain, stateToSuccess, successState,
1140                                        transitionProbability);
1141                }
1142 
1143                // Return the result:
1144                return markovChain;
1145        }
1146 
1147        /**
1148         * Creates a Markov chain for an internal action failing with probability
1149         * 1.0 because of unavailable hardware resources. The failure probability is
1150         * divided between all unavailable resources.
1151         * 
1152         * @param prefixes
1153         *            the prefixes of the chain name
1154         * @param failureDescriptions
1155         *            a list of failure descriptions for hardware resources
1156         * @return the resulting Markov Chain
1157         */
1158        public MarkovChain initResourceFailureMarkovChain(
1159                        final List<String> prefixes,
1160                        final List<FailureDescription> failureDescriptions) {
1161 
1162                // Create the Markov Chain Entity:
1163                MarkovChain markovChain = markovFactory.createMarkovChain();
1164                markovChain.setName(getName(prefixes));
1165 
1166                // Create the Start states:
1167                State startState = addState(markovChain, StateType.START,
1168                                StateType.START.toString(), prefixes);
1169                addState(markovChain, StateType.SUCCESS, StateType.SUCCESS.toString(),
1170                                prefixes);
1171 
1172                // Determine the failure probability for all unavailable resources:
1173                double failureProbability = 1.0 / failureDescriptions.size();
1174 
1175                // Create failure states and connecting transitions:
1176                for (FailureDescription description : failureDescriptions) {
1177                        State failureState = addStateForFailureDescription(markovChain,
1178                                        prefixes, description);
1179                        connectStates(markovChain, startState, failureState,
1180                                        failureProbability);
1181                }
1182 
1183                // Return the result:
1184                return markovChain;
1185        }
1186 
1187        /**
1188         * Creates a Markov Chain that represents a sequential execution path.
1189         * 
1190         * @param prefixes
1191         *            the prefixes of the Markov Chain name
1192         * @param stateNames
1193         *            the names of the states to create
1194         * @param statesOut
1195         *            the list of states created within the method that corresponds
1196         *            to the given list of state names
1197         * @return the resulting Markov Chain
1198         */
1199        public MarkovChain initSequentialMarkovChain(final List<String> prefixes,
1200                        final List<String> stateNames, final List<State> statesOut) {
1201 
1202                // Create the Markov Chain Entity:
1203                MarkovChain markovChain = markovFactory.createMarkovChain();
1204                markovChain.setName(getName(prefixes));
1205 
1206                // Create the Start and Success States:
1207                State startState = addState(markovChain, StateType.START,
1208                                StateType.START.toString(), prefixes);
1209                State successState = addState(markovChain, StateType.SUCCESS,
1210                                StateType.SUCCESS.toString(), prefixes);
1211 
1212                // Mark the State that will later lead directly to the Success State:
1213                State stateToSuccess = startState;
1214 
1215                // Go through the chain of state names:
1216                for (int i = 0; i < stateNames.size(); i++) {
1217 
1218                        // Create a Markov State for this Action:
1219                        State state = addState(markovChain, StateType.DEFAULT, stateNames
1220                                        .get(i), prefixes);
1221                        statesOut.add(state);
1222 
1223                        connectStates(markovChain, stateToSuccess, state, 1.0);
1224 
1225                        // Update the State leading to Success:
1226                        stateToSuccess = state;
1227                }
1228 
1229                // Create the Transition leading to the Success State:
1230                connectStates(markovChain, stateToSuccess, successState, 1.0);
1231 
1232                // Return the result:
1233                return markovChain;
1234        }
1235 
1236        /**
1237         * Checks if a failure-on-demand occurrence is contained in a given list of
1238         * handled failure types.
1239         * 
1240         * @param handledFailureTypeIds
1241         *            the list of handled failure types
1242         * @param occurredFailureTypeId
1243         *            the occurred failure type
1244         * @return true if the occurred failure type is included in the list of
1245         *         handled types
1246         */
1247        private boolean isFailureTypeHandled(
1248                        final List<String> handledFailureTypeIds,
1249                        final String occurredFailureTypeId) {
1250                for (String handledId : handledFailureTypeIds) {
1251                        if (occurredFailureTypeId.contains(handledId)) {
1252                                return true;
1253                        }
1254                }
1255                return false;
1256        }
1257 
1258        /**
1259         * Names a Transition.
1260         * 
1261         * @param transition
1262         *            the transition to name
1263         */
1264        private void nameTransition(final Transition transition) {
1265                transition.setName(transition.getFromState().getName() + " --> "
1266                                + transition.getToState().getName());
1267        }
1268 
1269        /**
1270         * Reduces the given Markov State in the given Markov Chain. The State is
1271         * deleted and all transitions leading to or starting from the State are
1272         * re-calculated so that the failure and success probabilities of the
1273         * overall Markov Chain are preserved.
1274         * 
1275         * @param markovChain
1276         *            the Markov Chain
1277         * @param stateToReduce
1278         *            the state which will be reduced
1279         */
1280        private void reduceState(final MarkovChain markovChain,
1281                        final State stateToReduce) {
1282 
1283                // Assure that the State which will be reduced is contained in the given
1284                // Markov Chain:
1285                if (!markovChain.getStates().contains(stateToReduce)) {
1286                        throw new MarkovException(
1287                                        "Cannot reduce Markov State. The Markov Chain does not contain that state.");
1288                }
1289 
1290                // Assure that the State which will be reduced is not the Start, Success
1291                // or Failure State:
1292                if (!stateToReduce.getType().equals(StateType.DEFAULT)) {
1293                        throw new MarkovException(
1294                                        "Cannot reduce Markov State. Only intermediate states can be reduced.");
1295                }
1296 
1297                // Find and delete all transitions in the Markov Chain that lead to the
1298                // reduceable State:
1299                ArrayList<Transition> transitionsToReduceState = findTransitionsToState(
1300                                markovChain, stateToReduce);
1301                deleteTransitions(markovChain, transitionsToReduceState);
1302 
1303                // Find and delete all transitions in the Markov Chain that start from
1304                // the reduceable State:
1305                ArrayList<Transition> transitionsFromReduceState = findTransitionsFromState(
1306                                markovChain, stateToReduce);
1307                deleteTransitions(markovChain, transitionsFromReduceState);
1308 
1309                // Delete the reduceable State:
1310                markovChain.getStates().remove(stateToReduce);
1311 
1312                // Build new transitions to replace the deleted ones:
1313                for (int i = 0; i < transitionsToReduceState.size(); i++) {
1314                        for (int j = 0; j < transitionsFromReduceState.size(); j++) {
1315 
1316                                // Create a new transition:
1317                                Transition transition = markovFactory.createTransition();
1318 
1319                                // Set the source and target States:
1320                                transition.setFromState(transitionsToReduceState.get(i)
1321                                                .getFromState());
1322                                transition.setToState(transitionsFromReduceState.get(j)
1323                                                .getToState());
1324 
1325                                // Calculate the transition probability:
1326                                transition.setProbability(transitionsToReduceState.get(i)
1327                                                .getProbability()
1328                                                * transitionsFromReduceState.get(j).getProbability());
1329 
1330                                // Set the name of the transition:
1331                                nameTransition(transition);
1332 
1333                                // Add the new Transition to the Markov Chain:
1334                                contributeTransition(markovChain, transition);
1335                        }
1336                }
1337        }
1338 
1339        /**
1340         * Removes duplicate failure states from the given Markov chain.
1341         * 
1342         * @param aggregateChain
1343         *            the chain to reduce
1344         * @param optimize
1345         *            indicates if Markov Chain reduction shall be performed during
1346         *            the transformation
1347         */
1348        private void removeDuplicateFailureStates(final MarkovChain markovChain,
1349                        final boolean optimize) {
1350 
1351                // Iterate over the failure states of the chain:
1352                List<State> failureStates = getFailureStates(markovChain);
1353                List<State> duplicateFailureStates = new ArrayList<State>();
1354                for (State failureState : failureStates) {
1355                        if (duplicateFailureStates.contains(failureState)) {
1356                                continue;
1357                        }
1358                        List<State> matchingFailureStates = findMatchingFailureStates(
1359                                        failureStates, failureState);
1360                        matchingFailureStates.remove(failureState);
1361                        for (State matchingState : matchingFailureStates) {
1362                                connectStates(markovChain, matchingState, failureState, 1.0);
1363                                matchingState.setType(StateType.DEFAULT);
1364                                duplicateFailureStates.add(matchingState);
1365                        }
1366                }
1367 
1368                // Optimize the aggregate MarkovChain:
1369                if (optimize) {
1370                        for (State duplicateState : duplicateFailureStates) {
1371                                reduceState(markovChain, duplicateState);
1372                        }
1373                }
1374        }
1375 
1376        /**
1377         * Checks if a Markov chain is valid. The chain is judged to be valid if
1378         * each transition has a source state and a target state, and if exactly one
1379         * start and success state exist. If a chain is not valid, a Markov
1380         * exception is thrown.
1381         * 
1382         * @param chain
1383         *            the Markov chain to check
1384         */
1385        private void validateChain(final MarkovChain chain) {
1386 
1387                // Check if each transition has a source and a target node:
1388                for (Transition t : chain.getTransitions()) {
1389                        if ((t.getFromState() == null) || (t.getToState() == null)) {
1390                                throw new MarkovException("Invalid transiton in Markov Chain.");
1391                        }
1392                }
1393 
1394                // Check if exactly one start and one success state are present:
1395                boolean hasStart = false;
1396                boolean hasSuccess = false;
1397                for (State s : chain.getStates()) {
1398                        if (s.getType() == StateType.START) {
1399                                if (hasStart) {
1400                                        throw new MarkovException(
1401                                                        "Multiple start states in Markov Chain.");
1402                                } else {
1403                                        hasStart = true;
1404                                }
1405                        } else if (s.getType() == StateType.SUCCESS) {
1406                                if (hasSuccess) {
1407                                        throw new MarkovException(
1408                                                        "Multiple success states in Markov Chain.");
1409                                } else {
1410                                        hasSuccess = true;
1411                                }
1412                        }
1413                }
1414 
1415                if (!hasStart) {
1416                        throw new MarkovException("No start state in Markov Chain.");
1417                }
1418 
1419                if (!hasSuccess) {
1420                        throw new MarkovException("No success state in Markov Chain.");
1421                }
1422 
1423                // TODO: Check for transitions leading to dead ends
1424                // TODO: Check for cycles
1425        }
1426}

[all classes][de.uka.ipd.sdq.reliability.solver.pcm2markov]
EMMA 2.0.9414 (unsupported private build) (C) Vladimir Roubtsov