aboutsummaryrefslogtreecommitdiffstats
path: root/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf
diff options
context:
space:
mode:
Diffstat (limited to 'Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf')
-rw-r--r--Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/cft2ft/Cft2FtTransformation.xtend24
-rw-r--r--Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/cft2ft/EventCollection.xtend90
-rw-r--r--Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/cft2ft/EventMaterializer.xtend208
-rw-r--r--Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/cft2ft/FaultTreeBuilder.xtend39
-rw-r--r--Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ecore2cft/ComponentFaultTreeTrace.xtend49
-rw-r--r--Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ecore2cft/ComponentInstanceTrace.xtend65
-rw-r--r--Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ecore2cft/ComponentNameGenerator.xtend16
-rw-r--r--Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ecore2cft/Ecore2CftTransformation.xtend28
-rw-r--r--Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ecore2cft/InputTrace.xtend35
-rw-r--r--Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ecore2cft/LookupHandler.xtend47
-rw-r--r--Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ecore2cft/MappingHandler.xtend91
-rw-r--r--Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ecore2cft/MappingQueries.xtend38
-rw-r--r--Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ft2galileo/Ft2GalileoTransformation.xtend57
-rw-r--r--Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/solver/ReliabilityResult.xtend51
-rw-r--r--Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/solver/StormDftConfiguration.xtend45
-rw-r--r--Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/solver/StormDftHandler.xtend182
-rw-r--r--Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/solver/StormDftSolver.xtend43
17 files changed, 1108 insertions, 0 deletions
diff --git a/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/cft2ft/Cft2FtTransformation.xtend b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/cft2ft/Cft2FtTransformation.xtend
new file mode 100644
index 00000000..a522654c
--- /dev/null
+++ b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/cft2ft/Cft2FtTransformation.xtend
@@ -0,0 +1,24 @@
1package hu.bme.mit.inf.dslreasoner.faulttree.transformation.cft2ft
2
3import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.ComponentFaultTree
4import hu.bme.mit.inf.dslreasoner.faulttree.model.ft.ConstantEvent
5import hu.bme.mit.inf.dslreasoner.faulttree.model.ft.FtFactory
6import hu.bme.mit.inf.dslreasoner.faulttree.model.ft.RandomEvent
7
8class Cft2FtTransformation {
9 def createFaultTree(ComponentFaultTree componentFaultTree) {
10 val materializer = new EventMaterializer
11 val topEvent = materializer.getOrMaterialize(componentFaultTree.topEvent)
12 switch (topEvent) {
13 ConstantEvent:
14 FtFactory.eINSTANCE.createConstantModel => [
15 failed = topEvent.failed
16 ]
17 RandomEvent: {
18 val builder = new FaultTreeBuilder
19 builder.addTopLevel(topEvent)
20 builder.faultTree
21 }
22 }
23 }
24}
diff --git a/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/cft2ft/EventCollection.xtend b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/cft2ft/EventCollection.xtend
new file mode 100644
index 00000000..102dc57e
--- /dev/null
+++ b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/cft2ft/EventCollection.xtend
@@ -0,0 +1,90 @@
1package hu.bme.mit.inf.dslreasoner.faulttree.transformation.cft2ft
2
3import com.google.common.collect.ImmutableSet
4import hu.bme.mit.inf.dslreasoner.faulttree.model.ft.ConstantEvent
5import hu.bme.mit.inf.dslreasoner.faulttree.model.ft.Event
6import hu.bme.mit.inf.dslreasoner.faulttree.model.ft.RandomEvent
7import java.util.Set
8import org.eclipse.xtend.lib.annotations.Data
9
10@Data
11class EventCollection {
12 val int falseEventCount
13 val int trueEventCount
14 val Set<RandomEvent> randomEvents
15
16 def containsFalseEvent() {
17 falseEventCount >= 1
18 }
19
20 def containsTrueEvent() {
21 trueEventCount >= 1
22 }
23
24 def getVariableEventCount() {
25 randomEvents.size
26 }
27
28 def containsRandomEvent() {
29 variableEventCount >= 1
30 }
31
32 def getCount() {
33 falseEventCount + trueEventCount + variableEventCount
34 }
35
36 def isEmpty() {
37 !containsFalseEvent && !containsTrueEvent && !containsRandomEvent
38 }
39
40 def containsExactlyOneRandomEvent() {
41 !containsFalseEvent && !containsTrueEvent && variableEventCount == 1
42 }
43
44 def toSingleRandomEvent() {
45 if (!containsExactlyOneRandomEvent) {
46 throw new IllegalStateException("Input collection is not a single random event")
47 }
48 randomEvents.head
49 }
50
51 static def builder() {
52 new Builder()
53 }
54
55 static class Builder {
56 var falseEventCount = 0
57 var trueEventCount = 0
58 val randomEventsBuilder = ImmutableSet.<RandomEvent>builder
59
60 private new() {
61 }
62
63 def add(Event event) {
64 switch (event) {
65 ConstantEvent:
66 if (event.failed) {
67 trueEventCount++
68 } else {
69 falseEventCount++
70 }
71 RandomEvent:
72 randomEventsBuilder.add(event)
73 default:
74 throw new IllegalArgumentException("Unknown event: " + event)
75 }
76 this
77 }
78
79 def addAll(EventCollection materializedEvens) {
80 falseEventCount += materializedEvens.falseEventCount
81 trueEventCount += materializedEvens.trueEventCount
82 randomEventsBuilder.addAll(materializedEvens.randomEvents)
83 this
84 }
85
86 def build() {
87 new EventCollection(falseEventCount, trueEventCount, randomEventsBuilder.build)
88 }
89 }
90}
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..6b3ed0d0
--- /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,208 @@
1package hu.bme.mit.inf.dslreasoner.faulttree.transformation.cft2ft
2
3import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.AndGateDefinition
4import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.BasicEventDefinition
5import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.Component
6import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.EventDeclaration
7import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.GateDefinition
8import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.InputEvent
9import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.KOfMGateDefinition
10import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.OrGateDefinition
11import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.Output
12import hu.bme.mit.inf.dslreasoner.faulttree.model.ft.ConstantEvent
13import hu.bme.mit.inf.dslreasoner.faulttree.model.ft.Event
14import hu.bme.mit.inf.dslreasoner.faulttree.model.ft.FtFactory
15import java.util.LinkedHashSet
16import java.util.Map
17import org.eclipse.emf.ecore.util.EcoreUtil
18import org.eclipse.xtend.lib.annotations.Data
19
20import static extension hu.bme.mit.inf.dslreasoner.faulttree.model.util.CftExtensions.*
21
22class EventMaterializer {
23 extension val FtFactory = FtFactory.eINSTANCE
24
25 val Map<EventKey<EventDeclaration>, Event> materializationCache = newHashMap
26 val Map<EventKey<InputEvent>, EventCollection> multipleInputCache = newHashMap
27 val ConstantEvent falseEvent
28 val ConstantEvent trueEvent
29 val path = new LinkedHashSet<EventKey<? extends EventDeclaration>>
30
31 new() {
32 falseEvent = createConstantEvent => [
33 failed = false
34 ]
35 trueEvent = createConstantEvent => [
36 failed = true
37 ]
38 }
39
40 def getOrMaterialize(Output output) {
41 getOrMaterialize(output.component, output.eventDeclaration)
42 }
43
44 def Event getOrMaterialize(Component component, EventDeclaration eventDeclaration) {
45 val eventKey = new EventKey(component, eventDeclaration)
46 pushEventKey(eventKey)
47 try {
48 // computeIfAbsent cannot be used recursively, so we must manually cache the event.
49 var event = materializationCache.get(eventKey)
50 if (event === null) {
51 event = materialize(component, eventDeclaration)
52 materializationCache.put(eventKey, event)
53 }
54 event
55 } finally {
56 popEventKey(eventKey)
57 }
58 }
59
60 protected def materialize(Component component, EventDeclaration eventDeclaration) {
61 val eventName = component.name + "_" + eventDeclaration.name
62 val event = switch (eventDeclaration) {
63 InputEvent:
64 return materializeConnectedEvent(component, eventDeclaration)
65 BasicEventDefinition: {
66 val basicEvent = createBasicEvent
67 basicEvent.distribution = EcoreUtil.copy(eventDeclaration.distribution)
68 basicEvent
69 }
70 GateDefinition: {
71 val inputs = collectInputs(component, eventDeclaration)
72 val gate = switch (eventDeclaration) {
73 AndGateDefinition:
74 if (inputs.containsFalseEvent) {
75 return falseEvent
76 } else if (inputs.empty) {
77 return trueEvent
78 } else if (inputs.containsExactlyOneRandomEvent) {
79 return inputs.toSingleRandomEvent
80 } else {
81 createAndGate
82 }
83 OrGateDefinition:
84 if (inputs.containsTrueEvent) {
85 return trueEvent
86 } else if (inputs.empty) {
87 return falseEvent
88 } else if (inputs.containsExactlyOneRandomEvent) {
89 return inputs.toSingleRandomEvent
90 } else {
91 createOrGate
92 }
93 KOfMGateDefinition: {
94 val requiredTrueInputs = inputs.count * eventDeclaration.k / eventDeclaration.m
95 val k = requiredTrueInputs - inputs.getTrueEventCount
96 val m = inputs.variableEventCount
97 if (k == 0) {
98 return trueEvent
99 } else if (k > m) {
100 return falseEvent
101 } else if (inputs.containsExactlyOneRandomEvent) {
102 return inputs.toSingleRandomEvent
103 } else if (k == 1) {
104 createOrGate
105 } else if (k == m) {
106 createAndGate
107 } else {
108 val kOfMGate = createKOfMGate
109 kOfMGate.k = k
110 kOfMGate
111 }
112 }
113 default:
114 throw new IllegalArgumentException("Unknown gate definition: " + eventDeclaration)
115 }
116 gate.inputEvents.addAll(inputs.getRandomEvents)
117 gate
118 }
119 default:
120 throw new IllegalArgumentException("Unknown event declaration: " + eventDeclaration)
121 }
122 event.name = eventName
123 event
124 }
125
126 protected def materializeConnectedEvent(Component component, InputEvent inputEvent) {
127 if (inputEvent.multiple) {
128 throw new IllegalArgumentException('''Cannot materialize multiple nput «component.name»_«inputEvent.name»''')
129 }
130 val input = findInput(component, inputEvent)
131 val incomingConnections = input.incomingConnections
132 if (incomingConnections.size != 1) {
133 throw new IllegalArgumentException('''Input «component.name»_«inputEvent.name» has «incomingConnections.size» connections instead of 1''')
134 }
135 val output = incomingConnections.head.output
136 getOrMaterialize(output.component, output.eventDeclaration)
137 }
138
139 protected def collectInputs(Component component, GateDefinition gateDefinition) {
140 val builder = EventCollection.builder
141 for (inputEventDeclaration : gateDefinition.inputEvents) {
142 switch (inputEventDeclaration) {
143 InputEvent case inputEventDeclaration.multiple: {
144 val materializedEvents = getOrMaterializeConnectedEvents(component, inputEventDeclaration)
145 builder.addAll(materializedEvents)
146 }
147 default:
148 builder.add(getOrMaterialize(component, inputEventDeclaration))
149 }
150 }
151 builder.build
152 }
153
154 protected def getOrMaterializeConnectedEvents(Component component, InputEvent inputEvent) {
155 val inputKey = new EventKey(component, inputEvent)
156 pushEventKey(inputKey)
157 try {
158 // computeIfAbsent cannot be used recursively, so we must manually cache the event.
159 var eventCollection = multipleInputCache.get(inputKey)
160 if (eventCollection === null) {
161 eventCollection = materializeConnectedEvents(component, inputEvent)
162 multipleInputCache.put(inputKey, eventCollection)
163 }
164 eventCollection
165 } finally {
166 popEventKey(inputKey)
167 }
168 }
169
170 protected def materializeConnectedEvents(Component component, InputEvent inputEvent) {
171 val input = findInput(component, inputEvent)
172 val builder = EventCollection.builder
173 for (connection : input.incomingConnections) {
174 if (connection.isCurrentlyConnected) {
175 val materializedEvent = getOrMaterialize(connection.output)
176 builder.add(materializedEvent)
177 }
178 }
179 builder.build
180 }
181
182 protected def findInput(Component component, InputEvent inputEvent) {
183 val input = component.inputs.findFirst[it.inputEvent == inputEvent]
184 if (input === null) {
185 throw new IllegalArgumentException('''No input «inputEvent» in component «component»''')
186 }
187 return input
188 }
189
190 private def pushEventKey(EventKey<? extends EventDeclaration> eventKey) {
191 if (!path.add(eventKey)) {
192 throw new IllegalStateException(
193 '''Circular dependency [«FOR ancestor : path»«ancestor», «ENDFOR»«eventKey»] detected''')
194 }
195 }
196
197 private def popEventKey(EventKey<? extends EventDeclaration> eventKey) {
198 path.remove(eventKey)
199 }
200
201 @Data
202 protected static class EventKey<T extends EventDeclaration> {
203 val Component component
204 val T event
205
206 override toString() '''«component.name»_«event.name»'''
207 }
208}
diff --git a/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/cft2ft/FaultTreeBuilder.xtend b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/cft2ft/FaultTreeBuilder.xtend
new file mode 100644
index 00000000..0b0afea6
--- /dev/null
+++ b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/cft2ft/FaultTreeBuilder.xtend
@@ -0,0 +1,39 @@
1package hu.bme.mit.inf.dslreasoner.faulttree.transformation.cft2ft
2
3import hu.bme.mit.inf.dslreasoner.faulttree.model.ft.FtFactory
4import hu.bme.mit.inf.dslreasoner.faulttree.model.ft.Gate
5import hu.bme.mit.inf.dslreasoner.faulttree.model.ft.RandomEvent
6import java.util.Collection
7import org.eclipse.xtend.lib.annotations.Accessors
8
9class FaultTreeBuilder {
10 @Accessors
11 val faultTree = FtFactory.eINSTANCE.createFaultTree
12
13 def addTopLevel(RandomEvent event) {
14 if (faultTree.topEvent !== null) {
15 throw new IllegalStateException("Top event was already set")
16 }
17 add(event)
18 faultTree.topEvent = event
19 }
20
21 protected def void add(RandomEvent event) {
22 if (faultTree.eContainer == faultTree) {
23 return
24 }
25 if (faultTree.eContainer !== null) {
26 throw new IllegalStateException("Event is already in a different fault tree")
27 }
28 faultTree.events += event
29 if (event instanceof Gate) {
30 addAll(event.inputEvents)
31 }
32 }
33
34 protected def addAll(Collection<RandomEvent> events) {
35 for (event : events) {
36 add(event)
37 }
38 }
39}
diff --git a/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ecore2cft/ComponentFaultTreeTrace.xtend b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ecore2cft/ComponentFaultTreeTrace.xtend
new file mode 100644
index 00000000..10c91fb4
--- /dev/null
+++ b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ecore2cft/ComponentFaultTreeTrace.xtend
@@ -0,0 +1,49 @@
1package hu.bme.mit.inf.dslreasoner.faulttree.transformation.ecore2cft
2
3import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.CftFactory
4import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.ComponentDefinition
5import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.Modality
6import java.util.Map
7import org.eclipse.viatra.query.runtime.api.IPatternMatch
8import org.eclipse.xtend.lib.annotations.Accessors
9
10class ComponentFaultTreeTrace {
11 @Accessors val componentFaultTree = CftFactory.eINSTANCE.createComponentFaultTree
12
13 val nameGenerator = new ComponentNameGenerator
14 val Map<IPatternMatch, ComponentInstanceTrace> componentInstancesMap = newHashMap
15
16 def instantiateComponent(IPatternMatch patternMatch, ComponentDefinition componenDefinition) {
17 instantiateComponent(patternMatch, componenDefinition, Modality.MUST, false)
18 }
19
20 def instantiateComponent(IPatternMatch patternMatch, ComponentDefinition componenDefinition, Modality exists,
21 boolean allowMultiple) {
22 if (componentInstancesMap.containsKey(patternMatch)) {
23 throw new IllegalArgumentException("Already instantiated component for match: " + patternMatch)
24 }
25 val componentTrace = new ComponentInstanceTrace(componentFaultTree, componenDefinition, nameGenerator,
26 exists, allowMultiple)
27 componentInstancesMap.put(patternMatch, componentTrace)
28 componentTrace
29 }
30
31 def setTopLevel(ComponentInstanceTrace trace) {
32 if (componentFaultTree.topEvent !== null) {
33 throw new IllegalArgumentException("Top level component already set")
34 }
35 val outputs = trace.outputs
36 if (outputs.size !== 1) {
37 throw new IllegalArgumentException("Top level component must have 1 output, got " + outputs.size +
38 " instead")
39 }
40 if (!trace.appearsExactlyOnce) {
41 throw new IllegalArgumentException("Top level must appear in the fault tree exactly once")
42 }
43 componentFaultTree.topEvent = outputs.head
44 }
45
46 def lookup(IPatternMatch patternMatch) {
47 componentInstancesMap.get(patternMatch)
48 }
49}
diff --git a/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ecore2cft/ComponentInstanceTrace.xtend b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ecore2cft/ComponentInstanceTrace.xtend
new file mode 100644
index 00000000..158ab2e1
--- /dev/null
+++ b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ecore2cft/ComponentInstanceTrace.xtend
@@ -0,0 +1,65 @@
1package hu.bme.mit.inf.dslreasoner.faulttree.transformation.ecore2cft
2
3import com.google.common.collect.Maps
4import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.CftFactory
5import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.ComponentDefinition
6import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.ComponentFaultTree
7import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.EventDeclaration
8import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.InputEvent
9import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.Modality
10import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.Output
11import java.util.Map
12
13import static extension hu.bme.mit.inf.dslreasoner.faulttree.model.util.CftExtensions.*
14
15class ComponentInstanceTrace {
16 val componentInstance = CftFactory.eINSTANCE.createComponent
17 val Map<InputEvent, InputTrace> inputEventsMap
18 val Map<EventDeclaration, Output> outputEventsMap
19
20 protected new(ComponentFaultTree faultTree, ComponentDefinition componentDefinition,
21 ComponentNameGenerator nameGenerator, Modality exists, boolean multipleAllowed) {
22 componentInstance.componentDefinition = componentDefinition
23 componentInstance.name = nameGenerator.nextName(componentDefinition)
24 componentInstance.exists = exists
25 componentInstance.multipleAllowed = multipleAllowed
26 inputEventsMap = Maps.newHashMapWithExpectedSize(componentDefinition.inputEvents.size)
27 for (inputEvent : componentDefinition.inputEvents) {
28 val inputTrace = new InputTrace(componentInstance, inputEvent)
29 inputEventsMap.put(inputEvent, inputTrace)
30 }
31 outputEventsMap = Maps.newHashMapWithExpectedSize(componentDefinition.outputEvents.size)
32 for (outputEvent : componentDefinition.outputEvents) {
33 val output = CftFactory.eINSTANCE.createOutput
34 output.eventDeclaration = outputEvent
35 componentInstance.outputs += output
36 outputEventsMap.put(outputEvent, output)
37 }
38 faultTree.components += componentInstance
39 }
40
41 def void assign(EventDeclaration inputEvent, ComponentInstanceTrace sourceComponent, EventDeclaration outputEvent) {
42 assign(inputEvent, sourceComponent, outputEvent, Modality.MUST)
43 }
44
45 def void assign(EventDeclaration inputEvent, ComponentInstanceTrace sourceComponent, EventDeclaration outputEvent,
46 Modality exists) {
47 val inputTrace = inputEventsMap.get(inputEvent)
48 if (inputTrace === null) {
49 throw new IllegalArgumentException("Unknown input: " + inputEvent)
50 }
51 val output = sourceComponent.outputEventsMap.get(outputEvent)
52 if (output === null) {
53 throw new IllegalArgumentException("Unknown output: " + outputEvent)
54 }
55 inputTrace.assign(output, exists)
56 }
57
58 protected def getOutputs() {
59 componentInstance.outputs
60 }
61
62 protected def appearsExactlyOnce() {
63 componentInstance.appearsExactlyOnce
64 }
65}
diff --git a/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ecore2cft/ComponentNameGenerator.xtend b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ecore2cft/ComponentNameGenerator.xtend
new file mode 100644
index 00000000..71d40a9b
--- /dev/null
+++ b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ecore2cft/ComponentNameGenerator.xtend
@@ -0,0 +1,16 @@
1package hu.bme.mit.inf.dslreasoner.faulttree.transformation.ecore2cft
2
3import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.ComponentDefinition
4import java.util.Map
5
6class ComponentNameGenerator {
7 static val DEFAULT_NAME = "__unnamed"
8
9 val Map<ComponentDefinition, Integer> instanceCounts = newHashMap
10
11 def nextName(ComponentDefinition componentDefinition) {
12 val instanceCount = instanceCounts.getOrDefault(componentDefinition, 0)
13 instanceCounts.put(componentDefinition, instanceCount + 1)
14 (componentDefinition.name ?: DEFAULT_NAME) + instanceCount
15 }
16}
diff --git a/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ecore2cft/Ecore2CftTransformation.xtend b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ecore2cft/Ecore2CftTransformation.xtend
new file mode 100644
index 00000000..062de3df
--- /dev/null
+++ b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ecore2cft/Ecore2CftTransformation.xtend
@@ -0,0 +1,28 @@
1package hu.bme.mit.inf.dslreasoner.faulttree.transformation.ecore2cft
2
3import com.google.common.collect.ImmutableList
4import hu.bme.mit.inf.dslreasoner.faulttree.components.cftLanguage.TransformationDefinition
5import java.util.List
6import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine
7
8class Ecore2CftTransformation {
9 val List<MappingHandler> mappingHandlers
10
11 new(TransformationDefinition transformationDefinition, ViatraQueryEngine viatraQueryEngine) {
12 val mappingQueries = new MappingQueries(transformationDefinition, viatraQueryEngine)
13 mappingHandlers = ImmutableList.copyOf(transformationDefinition.mappingDefinitions.map [ mappingDefinition |
14 new MappingHandler(mappingDefinition, mappingQueries)
15 ])
16 }
17
18 def createComponentFaultTree() {
19 val trace = new ComponentFaultTreeTrace
20 for (handler : mappingHandlers) {
21 handler.instantiateComponents(trace)
22 }
23 for (handler : mappingHandlers) {
24 handler.instantiateConnections(trace)
25 }
26 trace.componentFaultTree
27 }
28}
diff --git a/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ecore2cft/InputTrace.xtend b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ecore2cft/InputTrace.xtend
new file mode 100644
index 00000000..b892eff1
--- /dev/null
+++ b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ecore2cft/InputTrace.xtend
@@ -0,0 +1,35 @@
1package hu.bme.mit.inf.dslreasoner.faulttree.transformation.ecore2cft
2
3import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.CftFactory
4import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.Component
5import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.Connection
6import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.Input
7import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.InputEvent
8import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.Modality
9import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.Output
10import java.util.Map
11
12import static extension hu.bme.mit.inf.dslreasoner.faulttree.model.util.CftExtensions.*
13
14class InputTrace {
15 val Input input = CftFactory.eINSTANCE.createInput
16 val Map<Output, Connection> connectionsMap = newHashMap
17
18 protected new(Component component, InputEvent inputEvent) {
19 input.inputEvent = inputEvent
20 component.inputs += input
21 }
22
23 def void assign(Output output, Modality exists) {
24 val connection = connectionsMap.get(output)
25 if (connection === null) {
26 val newConnection = CftFactory.eINSTANCE.createConnection
27 newConnection.output = output
28 newConnection.exists = exists
29 input.incomingConnections += newConnection
30 connectionsMap.put(output, newConnection)
31 } else if (exists.isMoreConcreteThan(connection.exists)) {
32 connection.exists = exists
33 }
34 }
35}
diff --git a/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ecore2cft/LookupHandler.xtend b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ecore2cft/LookupHandler.xtend
new file mode 100644
index 00000000..3a06dcc3
--- /dev/null
+++ b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ecore2cft/LookupHandler.xtend
@@ -0,0 +1,47 @@
1package hu.bme.mit.inf.dslreasoner.faulttree.transformation.ecore2cft
2
3import hu.bme.mit.inf.dslreasoner.faulttree.components.cftLanguage.LookupDefinition
4import hu.bme.mit.inf.dslreasoner.faulttree.components.cftLanguage.MappingDefinition
5import org.eclipse.viatra.query.runtime.api.IPatternMatch
6import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher
7
8class LookupHandler {
9 val int[] argumentIndices
10 val ViatraQueryMatcher<? extends IPatternMatch> lookedUpMatcher
11
12 new(MappingDefinition mappingDefinition, LookupDefinition lookupDefinition,
13 ViatraQueryMatcher<? extends IPatternMatch> lookedUpMatcher) {
14 if (lookupDefinition.eContainer != mappingDefinition) {
15 throw new IllegalArgumentException("lookupDefinition must be contained in mappingDefinition")
16 }
17 val argumentCount = lookupDefinition.arguments.size
18 if (argumentCount != lookedUpMatcher.parameterNames.length) {
19 throw new IllegalArgumentException(
20 "lookupDefinition (name: " + lookupDefinition.mapping?.pattern?.name +
21 ") must have as many arguments as lookedUpMatcher (name: " + lookedUpMatcher.patternName + ")")
22 }
23 argumentIndices = newIntArrayOfSize(argumentCount)
24 for (var int i = 0; i < argumentCount; i++) {
25 val argument = lookupDefinition.arguments.get(i)
26 val argumentIndex = mappingDefinition.parameters.indexOf(argument)
27 argumentIndices.set(i, argumentIndex)
28 }
29 this.lookedUpMatcher = lookedUpMatcher
30 }
31
32 def lookupForMatch(ComponentFaultTreeTrace faultTreeTrace, IPatternMatch match) {
33 val lookedUpMatch = createLookedUpMatch(match)
34 faultTreeTrace.lookup(lookedUpMatch)
35 }
36
37 private def createLookedUpMatch(IPatternMatch match) {
38 val lookedUpMatch = lookedUpMatcher.newEmptyMatch
39 val argumentCount = argumentIndices.length
40 for (var int i = 0; i < argumentCount; i++) {
41 val argumentIndex = argumentIndices.get(i)
42 var argumentValue = match.get(argumentIndex)
43 lookedUpMatch.set(i, argumentValue)
44 }
45 lookedUpMatch
46 }
47}
diff --git a/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ecore2cft/MappingHandler.xtend b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ecore2cft/MappingHandler.xtend
new file mode 100644
index 00000000..643af5c4
--- /dev/null
+++ b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ecore2cft/MappingHandler.xtend
@@ -0,0 +1,91 @@
1package hu.bme.mit.inf.dslreasoner.faulttree.transformation.ecore2cft
2
3import com.google.common.collect.ImmutableMap
4import com.google.common.collect.Maps
5import hu.bme.mit.inf.dslreasoner.faulttree.components.cftLanguage.LookupDefinition
6import hu.bme.mit.inf.dslreasoner.faulttree.components.cftLanguage.MappingDefinition
7import hu.bme.mit.inf.dslreasoner.faulttree.components.cftLanguage.Variable
8import java.util.Map
9import org.eclipse.viatra.query.runtime.api.IPatternMatch
10import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher
11
12class MappingHandler {
13 val ViatraQueryMatcher<? extends IPatternMatch> matcher
14 val MappingDefinition mappingDefinition
15 val Map<LookupDefinition, LookupHandler> lookupHandlers
16
17 new(MappingDefinition mappingDefinition, MappingQueries mappingQueries) {
18 matcher = mappingQueries.getMatcher(mappingDefinition)
19 this.mappingDefinition = mappingDefinition
20 val variables = newHashSet
21 for (assignment : mappingDefinition.assignments) {
22 variables += assignment.input.component
23 variables += assignment.output.component
24 }
25 lookupHandlers = ImmutableMap.copyOf(variables.filter(LookupDefinition).toMap([it], [ lookupDefinition |
26 mappingQueries.createLookupHandler(mappingDefinition, lookupDefinition)
27 ]))
28 }
29
30 def instantiateComponents(ComponentFaultTreeTrace faultTreeTrace) {
31 if (!hasComponentInstace) {
32 return
33 }
34 matcher.forEachMatch [ match |
35 val componentTrace = faultTreeTrace.instantiateComponent(match, componentDefinition)
36 if (isTopLevel) {
37 faultTreeTrace.topLevel = componentTrace
38 }
39 ]
40 }
41
42 def instantiateConnections(ComponentFaultTreeTrace faultTreeTrace) {
43 if (!hasConnections) {
44 return
45 }
46 matcher.forEachMatch [ match |
47 val lookedUpComponents = lookupComponents(faultTreeTrace, match)
48 for (assignment : mappingDefinition.assignments) {
49 val input = assignment.input
50 val inputComponent = lookedUpComponents.get(input.component)
51 val output = assignment.output
52 val outputComponent = lookedUpComponents.get(output.component)
53 if (inputComponent !== null && outputComponent !== null) {
54 inputComponent.assign(input.event, outputComponent, output.event)
55 }
56 }
57 ]
58 }
59
60 private def Map<Variable, ComponentInstanceTrace> lookupComponents(ComponentFaultTreeTrace faultTreeTrace,
61 IPatternMatch match) {
62 val lookedUpComponents = Maps.newHashMapWithExpectedSize(lookupHandlers.size + 1)
63 if (hasComponentInstace) {
64 val componentInstance = faultTreeTrace.lookup(match)
65 lookedUpComponents.put(mappingDefinition.componentInstance, componentInstance)
66 }
67 for (pair : lookupHandlers.entrySet) {
68 val componentInstance = pair.value.lookupForMatch(faultTreeTrace, match)
69 if (componentInstance !== null) {
70 lookedUpComponents.put(pair.key, componentInstance)
71 }
72 }
73 lookedUpComponents
74 }
75
76 private def getComponentDefinition() {
77 mappingDefinition.componentInstance?.componentType
78 }
79
80 private def hasComponentInstace() {
81 componentDefinition !== null
82 }
83
84 private def isTopLevel() {
85 mappingDefinition.topLevel
86 }
87
88 private def hasConnections() {
89 !mappingDefinition.assignments.empty
90 }
91}
diff --git a/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ecore2cft/MappingQueries.xtend b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ecore2cft/MappingQueries.xtend
new file mode 100644
index 00000000..6683b3f8
--- /dev/null
+++ b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ecore2cft/MappingQueries.xtend
@@ -0,0 +1,38 @@
1package hu.bme.mit.inf.dslreasoner.faulttree.transformation.ecore2cft
2
3import com.google.common.collect.ImmutableMap
4import hu.bme.mit.inf.dslreasoner.faulttree.components.cftLanguage.LookupDefinition
5import hu.bme.mit.inf.dslreasoner.faulttree.components.cftLanguage.MappingDefinition
6import hu.bme.mit.inf.dslreasoner.faulttree.components.cftLanguage.TransformationDefinition
7import java.util.Map
8import org.eclipse.viatra.query.patternlanguage.emf.specification.SpecificationBuilder
9import org.eclipse.viatra.query.runtime.api.GenericQueryGroup
10import org.eclipse.viatra.query.runtime.api.IPatternMatch
11import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine
12import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher
13
14class MappingQueries {
15 val Map<MappingDefinition, ViatraQueryMatcher<? extends IPatternMatch>> matchersMap
16
17 new(TransformationDefinition transformationDefinition, ViatraQueryEngine viatraQueryEngine) {
18 val specificationBuilder = new SpecificationBuilder
19 val querySpecificationsMap = transformationDefinition.mappingDefinitions.toMap([it], [
20 specificationBuilder.getOrCreateSpecification(pattern)
21 ])
22 GenericQueryGroup.of(querySpecificationsMap.values).prepare(viatraQueryEngine)
23 matchersMap = ImmutableMap.copyOf(querySpecificationsMap.mapValues[getMatcher(viatraQueryEngine)])
24 }
25
26 def getMatcher(MappingDefinition mappingDefinition) {
27 val matcher = matchersMap.get(mappingDefinition)
28 if (matcher === null) {
29 throw new IllegalArgumentException("Unknown mapping definition: " + mappingDefinition)
30 }
31 matcher
32 }
33
34 def createLookupHandler(MappingDefinition mappingDefinition, LookupDefinition lookupDefinition) {
35 val lookedUpMatcher = getMatcher(lookupDefinition.mapping)
36 new LookupHandler(mappingDefinition, lookupDefinition, lookedUpMatcher)
37 }
38}
diff --git a/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ft2galileo/Ft2GalileoTransformation.xtend b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ft2galileo/Ft2GalileoTransformation.xtend
new file mode 100644
index 00000000..4a19e2cd
--- /dev/null
+++ b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ft2galileo/Ft2GalileoTransformation.xtend
@@ -0,0 +1,57 @@
1package hu.bme.mit.inf.dslreasoner.faulttree.transformation.ft2galileo
2
3import hu.bme.mit.inf.dslreasoner.faulttree.model.ft.AndGate
4import hu.bme.mit.inf.dslreasoner.faulttree.model.ft.BasicEvent
5import hu.bme.mit.inf.dslreasoner.faulttree.model.ft.ConstantDistribution
6import hu.bme.mit.inf.dslreasoner.faulttree.model.ft.Distribution
7import hu.bme.mit.inf.dslreasoner.faulttree.model.ft.ExponentialDistribution
8import hu.bme.mit.inf.dslreasoner.faulttree.model.ft.FaultTree
9import hu.bme.mit.inf.dslreasoner.faulttree.model.ft.Gate
10import hu.bme.mit.inf.dslreasoner.faulttree.model.ft.KOfMGate
11import hu.bme.mit.inf.dslreasoner.faulttree.model.ft.OrGate
12import hu.bme.mit.inf.dslreasoner.faulttree.model.ft.RandomEvent
13import org.eclipse.xtend2.lib.StringConcatenationClient
14
15class Ft2GalileoTransformation {
16 def toGalileo(FaultTree faultTree) '''
17 toplevel "«faultTree.topEvent.name»";
18 «FOR event : faultTree.events»
19 "«event.name»" «defineEvent(event)»;
20 «ENDFOR»
21 '''
22
23 protected dispatch def defineEvent(BasicEvent basicEvent) {
24 // ft-diet (https://moves.rwth-aachen.de/ft-diet/) needs a dormancy factor.
25 '''«defineDistribution(basicEvent.distribution)» dorm=0.0'''
26 }
27
28 protected dispatch def StringConcatenationClient defineDistribution(ConstantDistribution distribution) {
29 '''p=«distribution.p»'''
30 }
31
32 protected dispatch def StringConcatenationClient defineDistribution(ExponentialDistribution distribution) {
33 '''lambda=«distribution.lambda»'''
34 }
35
36 protected dispatch def StringConcatenationClient defineDistribution(Distribution distribution) {
37 throw new IllegalArgumentException("Unknown distribution: " + distribution)
38 }
39
40 protected dispatch def StringConcatenationClient defineEvent(Gate gate) {
41 '''«defineGate(gate)» «FOR input : gate.inputEvents SEPARATOR " "»"«input.name»"«ENDFOR»'''
42 }
43
44 protected dispatch def StringConcatenationClient defineGate(AndGate gate) '''and'''
45
46 protected dispatch def StringConcatenationClient defineGate(OrGate gate) '''or'''
47
48 protected dispatch def StringConcatenationClient defineGate(KOfMGate gate) '''«gate.k»of«gate.inputEvents.size»'''
49
50 protected dispatch def StringConcatenationClient defineGate(Gate gate) {
51 throw new IllegalArgumentException("Unknown gate: " + gate)
52 }
53
54 protected dispatch def StringConcatenationClient defineEvent(RandomEvent randomEvent) {
55 throw new IllegalArgumentException("Unknown random even: " + randomEvent)
56 }
57}
diff --git a/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/solver/ReliabilityResult.xtend b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/solver/ReliabilityResult.xtend
new file mode 100644
index 00000000..19c3d17d
--- /dev/null
+++ b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/solver/ReliabilityResult.xtend
@@ -0,0 +1,51 @@
1package hu.bme.mit.inf.dslreasoner.faulttree.transformation.solver
2
3import org.eclipse.xtend.lib.annotations.Data
4import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
5
6abstract class ReliabilityResult {
7 public static val TIMEOUT = new Unknown("Solver timed out")
8 public static val MEMOUT = new Unknown("Solver out of memory")
9
10 abstract def Solution getOrThrow()
11
12 @Data
13 static final class Solution extends ReliabilityResult {
14 val double lowerBound
15 val double upperBound
16
17 new(double value) {
18 this(value, value)
19 }
20
21 new(double lowerBound, double upperBound) {
22 if (lowerBound > upperBound) {
23 throw new IllegalArgumentException("lowerBound must not be larger than upperBound")
24 }
25 this.lowerBound = lowerBound
26 this.upperBound = upperBound
27 }
28
29 override getOrThrow() {
30 this
31 }
32 }
33
34 @Data
35 static final class Unknown extends ReliabilityResult {
36 val String message
37 val Throwable cause
38
39 @FinalFieldsConstructor
40 new() {
41 }
42
43 new(String message) {
44 this(message, null)
45 }
46
47 override getOrThrow() {
48 throw new RuntimeException(message, cause)
49 }
50 }
51}
diff --git a/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/solver/StormDftConfiguration.xtend b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/solver/StormDftConfiguration.xtend
new file mode 100644
index 00000000..d9059bfc
--- /dev/null
+++ b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/solver/StormDftConfiguration.xtend
@@ -0,0 +1,45 @@
1package hu.bme.mit.inf.dslreasoner.faulttree.transformation.solver
2
3import hu.bme.mit.inf.dslreasoner.logic.model.builder.SolverConfiguration
4
5final class StormDftConfiguration extends SolverConfiguration {
6 public static val DEFAULT_SOLVER_PATH = "storm-dft"
7
8 public double precision = 1e-6
9
10 public boolean bisimulation = true
11
12 public boolean symmetryReduction = true
13
14 public boolean modularization = true
15
16 public boolean dontCarePropagation = true
17
18 public double approximation = 0
19
20 public var approximationHeuristic = ApproximationHeuristic.NONE
21
22 public FtAnalysisObjective objective
23
24 def isApproximationInUse() {
25 approximationHeuristic != ApproximationHeuristic.NONE
26 }
27}
28
29abstract class FtAnalysisObjective {
30 public static val MTTF = new FtAnalysisObjective {
31 }
32
33 private new() {
34 }
35
36 static final class TimeBound extends FtAnalysisObjective {
37 public double timeBound = 0
38 }
39}
40
41enum ApproximationHeuristic {
42 NONE,
43 DEPTH
44// See https://github.com/moves-rwth/storm/issues/35 for additional approximation heuristics.
45}
diff --git a/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/solver/StormDftHandler.xtend b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/solver/StormDftHandler.xtend
new file mode 100644
index 00000000..a250a955
--- /dev/null
+++ b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/solver/StormDftHandler.xtend
@@ -0,0 +1,182 @@
1package hu.bme.mit.inf.dslreasoner.faulttree.transformation.solver
2
3import com.google.common.collect.ImmutableList
4import hu.bme.mit.inf.dslreasoner.logic.model.builder.DocumentationLevel
5import hu.bme.mit.inf.dslreasoner.logic.model.builder.SolverConfiguration
6import java.io.BufferedReader
7import java.io.IOException
8import java.io.InputStream
9import java.io.InputStreamReader
10import java.util.regex.Pattern
11
12class StormDftException extends RuntimeException {
13 new(String s) {
14 super(s)
15 }
16
17 new(String s, Exception e) {
18 super(s, e)
19 }
20}
21
22class StormDftHandler {
23 static val DOUBLE_REGEX = "[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?"
24 static val SINGLE_RESULT_GROUP = "single"
25 static val LOWER_BOUND_GROUP = "lower"
26 static val UPPER_BOUND_GROUP = "upper"
27 static val RESULT_REGEX = '''^Result:\s*\[(?:(?<«SINGLE_RESULT_GROUP»>«DOUBLE_REGEX»)|\((?<«LOWER_BOUND_GROUP»>«DOUBLE_REGEX»),\s*(?<«UPPER_BOUND_GROUP»>«DOUBLE_REGEX»)\))\]'''
28 static val RESULT_PATTERN = Pattern.compile(RESULT_REGEX)
29
30 static val SIGNAL_EXIT_VALUE_OFFSET = 0x80
31 static val SIGXCPU = 24
32 static val SIGXFSZ = 25
33
34 static val STORM_GENERAL_ERROR = (-1).bitwiseAnd(0xff)
35 static val STORM_TIMEOUT = (-2).bitwiseAnd(0xff)
36 static val STORM_MEMOUT = (-3).bitwiseAnd(0xff)
37
38 def callSolver(String dftFilePath, StormDftConfiguration configuration) {
39 val commandLine = configuration.toCommandLine(dftFilePath)
40 val documentationLevel = configuration.documentationLevel
41 val printOutput = documentationLevel == DocumentationLevel.NORMAL ||
42 documentationLevel == DocumentationLevel.FULL
43 val processBuilder = new ProcessBuilder().command(commandLine)
44 var Process process = null
45 try {
46 try {
47 process = processBuilder.start
48 process.outputStream.close
49 val result = readOutput(process.inputStream, printOutput)
50 val error = readError(process.errorStream, printOutput)
51 val exitValue = process.waitFor
52 if (result === null) {
53 interpretExitStatus(exitValue, error)
54 } else {
55 result
56 }
57 } catch (IOException e) {
58 throw new StormDftException("Error during input/output handling of the stochastic solver.", e)
59 }
60 } catch (Exception e) {
61 if (process !== null) {
62 process.destroyForcibly.waitFor
63 }
64 throw e
65 }
66 }
67
68 private def toCommandLine(extension StormDftConfiguration configuration, String dftFilePath) {
69 extension val optionsBuilder = ImmutableList.builder
70 add(solverPath ?: StormDftConfiguration.DEFAULT_SOLVER_PATH)
71 if (runtimeLimit != SolverConfiguration.Unlimited) {
72 add("--timeout", runtimeLimit.toString)
73 }
74 add("--precision", precision.toString)
75 if (bisimulation) {
76 add("--bisimulation")
77 }
78 if (symmetryReduction) {
79 add("--symmetryreduction")
80 }
81 if (modularization) {
82 add("--modularisation")
83 }
84 if (!dontCarePropagation) {
85 add("--disabledc")
86 }
87 if (approximationInUse) {
88 val heuristicName = switch (approximationHeuristic) {
89 case DEPTH:
90 "depth"
91 default:
92 throw new IllegalArgumentException("Unknown approximation heuristic: " + approximationHeuristic)
93 }
94 add("--approximation", approximation.toString, "--approximationheuristic", heuristicName)
95 }
96 add("--dftfile", dftFilePath)
97 switch (objective) {
98 case FtAnalysisObjective.MTTF:
99 add("--expectedtime")
100 FtAnalysisObjective.TimeBound:
101 add("--timebound")
102 default:
103 throw new IllegalArgumentException("Unknown analysis objective: " + objective)
104 }
105 if (documentationLevel == DocumentationLevel.FULL) {
106 add("--verbose")
107 }
108 build
109 }
110
111 private def readOutput(InputStream inputStream, boolean printOutput) {
112 val bufferedReader = new BufferedReader(new InputStreamReader(inputStream))
113 try {
114 var String line
115 while ((line = bufferedReader.readLine) !== null) {
116 if (printOutput) {
117 println(line)
118 }
119 val matcher = RESULT_PATTERN.matcher(line)
120 if (matcher.find) {
121 try {
122 val single = matcher.group(SINGLE_RESULT_GROUP)
123 if (single !== null) {
124 val singleValue = Double.parseDouble(single)
125 return new ReliabilityResult.Solution(singleValue)
126 }
127 val lower = matcher.group(LOWER_BOUND_GROUP)
128 val upper = matcher.group(UPPER_BOUND_GROUP)
129 if (lower !== null && upper !== null) {
130 val lowerValue = Double.parseDouble(lower)
131 val upperValue = Double.parseDouble(upper)
132 return new ReliabilityResult.Solution(lowerValue, upperValue)
133 }
134 throw new StormDftException("Inconsistent stochastic solver output: " + line)
135 } catch (NumberFormatException e) {
136 throw new StormDftException("Malformatted number from stochastic solver.", e)
137 }
138 }
139 }
140 } finally {
141 bufferedReader.close
142 }
143 null
144 }
145
146 private def readError(InputStream inputStream, boolean printOutput) {
147 val bufferedReader = new BufferedReader(new InputStreamReader(inputStream))
148 try {
149 val lines = newArrayList
150 var String line
151 while ((line = bufferedReader.readLine) !== null) {
152 if (printOutput) {
153 System.err.println(line)
154 }
155 lines += line
156 }
157 lines.join("\n")
158 } finally {
159 bufferedReader.close
160 }
161 }
162
163 private def interpretExitStatus(int exitValue, String error) {
164 switch (exitValue) {
165 case STORM_GENERAL_ERROR:
166 throw new StormDftException("Storm error: " + error)
167 case STORM_TIMEOUT,
168 case SIGNAL_EXIT_VALUE_OFFSET + SIGXCPU:
169 ReliabilityResult.TIMEOUT
170 case STORM_MEMOUT,
171 case SIGNAL_EXIT_VALUE_OFFSET + SIGXFSZ:
172 ReliabilityResult.MEMOUT
173 default: {
174 if (exitValue > SIGNAL_EXIT_VALUE_OFFSET) {
175 val signalNumber = exitValue - SIGNAL_EXIT_VALUE_OFFSET
176 throw new StormDftException("Storm unexpectedly killed by signal " + signalNumber + ": " + error)
177 }
178 throw new StormDftException("Storm unexpectedly exit with status " + exitValue + ": " + error)
179 }
180 }
181 }
182}
diff --git a/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/solver/StormDftSolver.xtend b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/solver/StormDftSolver.xtend
new file mode 100644
index 00000000..931b9f39
--- /dev/null
+++ b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/solver/StormDftSolver.xtend
@@ -0,0 +1,43 @@
1package hu.bme.mit.inf.dslreasoner.faulttree.transformation.solver
2
3import hu.bme.mit.inf.dslreasoner.faulttree.model.ft.ConstantModel
4import hu.bme.mit.inf.dslreasoner.faulttree.model.ft.FaultTree
5import hu.bme.mit.inf.dslreasoner.faulttree.model.ft.ReliabilityModel
6import hu.bme.mit.inf.dslreasoner.faulttree.transformation.ft2galileo.Ft2GalileoTransformation
7import hu.bme.mit.inf.dslreasoner.workspace.ReasonerWorkspace
8
9class StormDftSolver {
10 static val DFT_FILE_NAME = "ft.dft"
11
12 val ft2Galileo = new Ft2GalileoTransformation
13 val handler = new StormDftHandler
14
15 def solve(ReliabilityModel reliabilityModel, StormDftConfiguration configuration,
16 ReasonerWorkspace reasonerWorkspace) {
17 switch (reliabilityModel) {
18 FaultTree:
19 solve(reliabilityModel, configuration, reasonerWorkspace)
20 ConstantModel: {
21 val result = if (reliabilityModel.failed) {
22 0
23 } else {
24 switch (objective : configuration.objective) {
25 case FtAnalysisObjective.MTTF: Double.POSITIVE_INFINITY
26 FtAnalysisObjective.TimeBound: 1
27 default: throw new IllegalArgumentException("Unknown objective: " + objective)
28 }
29 }
30 new ReliabilityResult.Solution(result)
31 }
32 default:
33 throw new IllegalArgumentException("Unknown reliability model: " + reliabilityModel)
34 }
35 }
36
37 def solve(FaultTree faultTree, StormDftConfiguration configuration, ReasonerWorkspace reasonerWorkspace) {
38 val galileo = ft2Galileo.toGalileo(faultTree)
39 reasonerWorkspace.writeText(DFT_FILE_NAME, galileo)
40 val dftFilePath = reasonerWorkspace.getFile(DFT_FILE_NAME).absolutePath
41 handler.callSolver(dftFilePath, configuration)
42 }
43}