diff options
author | Kristóf Marussy <kris7topher@gmail.com> | 2019-02-16 00:43:11 +0100 |
---|---|---|
committer | Kristóf Marussy <kris7topher@gmail.com> | 2019-02-19 19:18:25 +0100 |
commit | d90bedacaafe87e06fddaa05a6ff9b7b796e97e7 (patch) | |
tree | 3631e27854b40de3bce7606f60113054c77bd391 /Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/cft2ft/EventMaterializer.xtend | |
parent | Ecore2Cft transformation (diff) | |
download | VIATRA-Generator-d90bedacaafe87e06fddaa05a6ff9b7b796e97e7.tar.gz VIATRA-Generator-d90bedacaafe87e06fddaa05a6ff9b7b796e97e7.tar.zst VIATRA-Generator-d90bedacaafe87e06fddaa05a6ff9b7b796e97e7.zip |
Two-valued fault tree analyzer WIP
Diffstat (limited to 'Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/cft2ft/EventMaterializer.xtend')
-rw-r--r-- | Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/cft2ft/EventMaterializer.xtend | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/cft2ft/EventMaterializer.xtend b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/cft2ft/EventMaterializer.xtend new file mode 100644 index 00000000..85396e4d --- /dev/null +++ b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/cft2ft/EventMaterializer.xtend | |||
@@ -0,0 +1,192 @@ | |||
1 | package hu.bme.mit.inf.dslreasoner.faulttree.transformation.cft2ft | ||
2 | |||
3 | import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.AndGateDefinition | ||
4 | import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.BasicEventDefinition | ||
5 | import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.Component | ||
6 | import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.EventDeclaration | ||
7 | import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.GateDefinition | ||
8 | import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.InputEvent | ||
9 | import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.KOfMGateDefinition | ||
10 | import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.OrGateDefinition | ||
11 | import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.Output | ||
12 | import hu.bme.mit.inf.dslreasoner.faulttree.model.ft.ConstantEvent | ||
13 | import hu.bme.mit.inf.dslreasoner.faulttree.model.ft.Event | ||
14 | import hu.bme.mit.inf.dslreasoner.faulttree.model.ft.FtFactory | ||
15 | import java.util.LinkedHashSet | ||
16 | import java.util.Map | ||
17 | import org.eclipse.emf.ecore.util.EcoreUtil | ||
18 | import org.eclipse.xtend.lib.annotations.Data | ||
19 | |||
20 | class EventMaterializer { | ||
21 | extension val FtFactory = FtFactory.eINSTANCE | ||
22 | |||
23 | val Map<EventKey<EventDeclaration>, Event> materializationCache = newHashMap | ||
24 | val Map<EventKey<InputEvent>, EventCollection> multipleInputCache = newHashMap | ||
25 | val ConstantEvent falseEvent | ||
26 | val ConstantEvent trueEvent | ||
27 | val path = new LinkedHashSet<EventKey<? extends EventDeclaration>> | ||
28 | |||
29 | new() { | ||
30 | falseEvent = createConstantEvent => [ | ||
31 | failed = false | ||
32 | ] | ||
33 | trueEvent = createConstantEvent => [ | ||
34 | failed = true | ||
35 | ] | ||
36 | } | ||
37 | |||
38 | def getOrMaterialize(Output output) { | ||
39 | getOrMaterialize(output.component, output.eventDeclaration) | ||
40 | } | ||
41 | |||
42 | def Event getOrMaterialize(Component component, EventDeclaration eventDeclaration) { | ||
43 | val eventKey = new EventKey(component, eventDeclaration) | ||
44 | pushEventKey(eventKey) | ||
45 | try { | ||
46 | materializationCache.computeIfAbsent(eventKey)[materialize(it.component, it.event)] | ||
47 | } finally { | ||
48 | popEventKey(eventKey) | ||
49 | } | ||
50 | } | ||
51 | |||
52 | protected def materialize(Component component, EventDeclaration eventDeclaration) { | ||
53 | val eventName = component.name + "_" + eventDeclaration.name | ||
54 | val event = switch (eventDeclaration) { | ||
55 | InputEvent: | ||
56 | return materializeConnectedEvent(component, eventDeclaration) | ||
57 | BasicEventDefinition: { | ||
58 | val basicEvent = createBasicEvent | ||
59 | basicEvent.distribution = EcoreUtil.copy(eventDeclaration.distribution) | ||
60 | basicEvent | ||
61 | } | ||
62 | GateDefinition: { | ||
63 | val inputs = collectInputs(component, eventDeclaration) | ||
64 | val gate = switch (eventDeclaration) { | ||
65 | AndGateDefinition: | ||
66 | if (inputs.containsFalseEvent) { | ||
67 | return falseEvent | ||
68 | } else if (inputs.empty) { | ||
69 | return trueEvent | ||
70 | } else if (inputs.containsExactlyOneRandomEvent) { | ||
71 | return inputs.toSingleRandomEvent | ||
72 | } else { | ||
73 | createAndGate | ||
74 | } | ||
75 | OrGateDefinition: | ||
76 | if (inputs.containsTrueEvent) { | ||
77 | return trueEvent | ||
78 | } else if (inputs.empty) { | ||
79 | return falseEvent | ||
80 | } else if (inputs.containsExactlyOneRandomEvent) { | ||
81 | return inputs.toSingleRandomEvent | ||
82 | } else { | ||
83 | createOrGate | ||
84 | } | ||
85 | KOfMGateDefinition: { | ||
86 | val requiredTrueInputs = inputs.count * eventDeclaration.k / eventDeclaration.m | ||
87 | val k = requiredTrueInputs - inputs.getTrueEventCount | ||
88 | val m = inputs.variableEventCount | ||
89 | if (k == 0) { | ||
90 | return trueEvent | ||
91 | } else if (k > m) { | ||
92 | return falseEvent | ||
93 | } else if (inputs.containsExactlyOneRandomEvent) { | ||
94 | return inputs.toSingleRandomEvent | ||
95 | } else if (k == 1) { | ||
96 | createOrGate | ||
97 | } else if (k == m) { | ||
98 | createAndGate | ||
99 | } else { | ||
100 | val kOfMGate = createKOfMGate | ||
101 | kOfMGate.k = k | ||
102 | kOfMGate | ||
103 | } | ||
104 | } | ||
105 | default: | ||
106 | throw new IllegalArgumentException("Unknown gate definition: " + eventDeclaration) | ||
107 | } | ||
108 | gate.inputEvents.addAll(inputs.getRandomEvents) | ||
109 | gate | ||
110 | } | ||
111 | default: | ||
112 | throw new IllegalArgumentException("Unknown event declaration: " + eventDeclaration) | ||
113 | } | ||
114 | event.name = eventName | ||
115 | event | ||
116 | } | ||
117 | |||
118 | protected def materializeConnectedEvent(Component component, InputEvent inputEvent) { | ||
119 | if (inputEvent.multiple) { | ||
120 | throw new IllegalArgumentException('''Cannot materialize multiple nput «component.name»_«inputEvent.name»''') | ||
121 | } | ||
122 | val input = findInput(component, inputEvent) | ||
123 | val incomingConnections = input.incomingConnections | ||
124 | if (incomingConnections.size != 1) { | ||
125 | throw new IllegalArgumentException('''Input «component.name»_«inputEvent.name» has «incomingConnections.size» connections instead of 1''') | ||
126 | } | ||
127 | val output = incomingConnections.head.output | ||
128 | getOrMaterialize(output.component, output.eventDeclaration) | ||
129 | } | ||
130 | |||
131 | protected def collectInputs(Component component, GateDefinition gateDefinition) { | ||
132 | val builder = EventCollection.builder | ||
133 | for (inputEventDeclaration : gateDefinition.inputEvents) { | ||
134 | switch (inputEventDeclaration) { | ||
135 | InputEvent case inputEventDeclaration.multiple: { | ||
136 | val materializedEvents = getOrMaterializeConnectedEvents(component, inputEventDeclaration) | ||
137 | builder.addAll(materializedEvents) | ||
138 | } | ||
139 | default: | ||
140 | builder.add(getOrMaterialize(component, inputEventDeclaration)) | ||
141 | } | ||
142 | } | ||
143 | builder.build | ||
144 | } | ||
145 | |||
146 | protected def getOrMaterializeConnectedEvents(Component component, InputEvent inputEvent) { | ||
147 | val inputKey = new EventKey(component, inputEvent) | ||
148 | pushEventKey(inputKey) | ||
149 | try { | ||
150 | multipleInputCache.computeIfAbsent(inputKey)[materializeConnectedEvents(it.component, it.event)] | ||
151 | } finally { | ||
152 | popEventKey(inputKey) | ||
153 | } | ||
154 | } | ||
155 | |||
156 | protected def materializeConnectedEvents(Component component, InputEvent inputEvent) { | ||
157 | val input = findInput(component, inputEvent) | ||
158 | val builder = EventCollection.builder | ||
159 | for (connection : input.incomingConnections) { | ||
160 | val materializedEvent = getOrMaterialize(connection.output) | ||
161 | builder.add(materializedEvent) | ||
162 | } | ||
163 | builder.build | ||
164 | } | ||
165 | |||
166 | protected def findInput(Component component, InputEvent inputEvent) { | ||
167 | val input = component.inputs.findFirst[it.inputEvent == inputEvent] | ||
168 | if (input === null) { | ||
169 | throw new IllegalArgumentException('''No input «inputEvent» in component «component»''') | ||
170 | } | ||
171 | return input | ||
172 | } | ||
173 | |||
174 | private def pushEventKey(EventKey<? extends EventDeclaration> eventKey) { | ||
175 | if (!path.add(eventKey)) { | ||
176 | throw new IllegalStateException( | ||
177 | '''Circular dependency [«FOR ancestor : path»«ancestor», «ENDFOR»«eventKey»] detected''') | ||
178 | } | ||
179 | } | ||
180 | |||
181 | private def popEventKey(EventKey<? extends EventDeclaration> eventKey) { | ||
182 | path.remove(eventKey) | ||
183 | } | ||
184 | |||
185 | @Data | ||
186 | protected static class EventKey<T extends EventDeclaration> { | ||
187 | val Component component | ||
188 | val T event | ||
189 | |||
190 | override toString() '''«component.name»_«event.name»''' | ||
191 | } | ||
192 | } | ||