aboutsummaryrefslogtreecommitdiffstats
path: root/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit
diff options
context:
space:
mode:
Diffstat (limited to 'Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit')
-rw-r--r--Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/cft2ft/Cft2FtTransformation.xtend20
-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.xtend192
-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/Ecore2CftTransformation.xtend1
-rw-r--r--Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ft2galileo/Ft2GalileoTransformation.xtend56
-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.xtend186
-rw-r--r--Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/solver/StormDftSolver.xtend43
10 files changed, 720 insertions, 3 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
index caaffc3c..a522654c 100644
--- 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
@@ -1,10 +1,24 @@
1package hu.bme.mit.inf.dslreasoner.faulttree.transformation.cft2ft 1package hu.bme.mit.inf.dslreasoner.faulttree.transformation.cft2ft
2 2
3import hu.bme.mit.inf.dslreasoner.faulttree.model.cft.ComponentFaultTree 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
4 7
5class Cft2FtTransformation { 8class Cft2FtTransformation {
6 def createFaultTree(ComponentFaultTree componentFaultTree) { 9 def createFaultTree(ComponentFaultTree componentFaultTree) {
7 // TODO 10 val materializer = new EventMaterializer
8 throw new UnsupportedOperationException() 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 }
9 } 23 }
10} \ No newline at end of file 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..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 @@
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
20class 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}
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/Ecore2CftTransformation.xtend b/Stochastic/hu.bme.mit.inf.dslreasoner.faulttree.transformation/src/hu/bme/mit/inf/dslreasoner/faulttree/transformation/ecore2cft/Ecore2CftTransformation.xtend
index 36aac5e1..062de3df 100644
--- 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
@@ -23,5 +23,6 @@ class Ecore2CftTransformation {
23 for (handler : mappingHandlers) { 23 for (handler : mappingHandlers) {
24 handler.instantiateConnections(trace) 24 handler.instantiateConnections(trace)
25 } 25 }
26 trace.componentFaultTree
26 } 27 }
27} 28}
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..732d9fed
--- /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,56 @@
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 defineDistribution(basicEvent.distribution)
25 }
26
27 protected dispatch def StringConcatenationClient defineDistribution(ConstantDistribution distribution) {
28 '''p=«distribution.p»'''
29 }
30
31 protected dispatch def StringConcatenationClient defineDistribution(ExponentialDistribution distribution) {
32 '''lambda=«distribution.lambda»'''
33 }
34
35 protected dispatch def StringConcatenationClient defineDistribution(Distribution distribution) {
36 throw new IllegalArgumentException("Unknown distribution: " + distribution)
37 }
38
39 protected dispatch def StringConcatenationClient defineEvent(Gate gate) {
40 '''«defineGate(gate)» «FOR input : gate.inputEvents SEPARATOR " "»«input.name»«ENDFOR»'''
41 }
42
43 protected dispatch def StringConcatenationClient defineGate(AndGate gate) '''and'''
44
45 protected dispatch def StringConcatenationClient defineGate(OrGate gate) '''or'''
46
47 protected dispatch def StringConcatenationClient defineGate(KOfMGate gate) '''«gate.k»of«gate.inputEvents.size»'''
48
49 protected dispatch def StringConcatenationClient defineGate(Gate gate) {
50 throw new IllegalArgumentException("Unknown gate: " + gate)
51 }
52
53 protected dispatch def StringConcatenationClient defineEvent(RandomEvent randomEvent) {
54 throw new IllegalArgumentException("Unknown random even: " + randomEvent)
55 }
56}
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..91c6a0d0
--- /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,186 @@
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
11import jnr.constants.platform.Signal
12import org.apache.commons.lang.SystemUtils
13
14class StormDftException extends RuntimeException {
15 new(String s) {
16 super(s)
17 }
18
19 new(String s, Exception e) {
20 super(s, e)
21 }
22}
23
24class StormDftHandler {
25 static val DOUBLE_REGEX = "[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?"
26 static val SINGLE_RESULT_GROUP = "single"
27 static val LOWER_BOUND_GROUP = "lower"
28 static val UPPER_BOUND_GROUP = "upper"
29 static val RESULT_REGEX = '''^Result:\s*\[(?:(?<«SINGLE_RESULT_GROUP»>«DOUBLE_REGEX»)|\((?<«LOWER_BOUND_GROUP»>«DOUBLE_REGEX»),\s*(?<«UPPER_BOUND_GROUP»>«DOUBLE_REGEX»)\))\]'''
30 static val RESULT_PATTERN = Pattern.compile(RESULT_REGEX)
31
32 // See http://hg.openjdk.java.net/jdk7/jdk7/jdk/file/jdk7-b147/src/solaris/native/java/lang/UNIXProcess_md.c#l332
33 static val SIGNAL_EXIT_VALUE_OFFSET = if(SystemUtils.IS_OS_SOLARIS) 0 else 0x80
34
35 static val STORM_GENERAL_ERROR = (-1).bitwiseAnd(0xff)
36 static val STORM_TIMEOUT = (-2).bitwiseAnd(0xff)
37 static val STORM_MEMOUT = (-3).bitwiseAnd(0xff)
38
39 def callSolver(String dftFilePath, StormDftConfiguration configuration) {
40 val commandLine = configuration.toCommandLine(dftFilePath)
41 val documentationLevel = configuration.documentationLevel
42 val printOutput = documentationLevel == DocumentationLevel.NORMAL ||
43 documentationLevel == DocumentationLevel.FULL
44 val processBuilder = new ProcessBuilder().command(commandLine)
45 var Process process = null
46 try {
47 try {
48 process = processBuilder.start
49 process.outputStream.close
50 val result = readOutput(process.inputStream, printOutput)
51 val error = readError(process.errorStream, printOutput)
52 val exitValue = process.waitFor
53 if (result === null) {
54 interpretExitStatus(exitValue, error)
55 } else {
56 result
57 }
58 } catch (IOException e) {
59 throw new StormDftException("Error during input/output handling of the stochastic solver.", e)
60 }
61 } catch (Exception e) {
62 if (process !== null) {
63 process.destroyForcibly.waitFor
64 }
65 throw e
66 }
67 }
68
69 private def toCommandLine(extension StormDftConfiguration configuration, String dftFilePath) {
70 extension val optionsBuilder = ImmutableList.builder
71 add(solverPath ?: StormDftConfiguration.DEFAULT_SOLVER_PATH)
72 if (runtimeLimit != SolverConfiguration.Unlimited) {
73 add("--timeout", runtimeLimit.toString)
74 }
75 add("--precision", precision.toString)
76 if (bisimulation) {
77 add("--bisimulation")
78 }
79 if (symmetryReduction) {
80 add("--symmetryreduction")
81 }
82 if (modularization) {
83 add("--modularisation")
84 }
85 if (!dontCarePropagation) {
86 add("--disabledc")
87 }
88 if (approximationInUse) {
89 val heuristicName = switch (approximationHeuristic) {
90 case DEPTH:
91 "depth"
92 default:
93 throw new IllegalArgumentException("Unknown approximation heuristic: " + approximationHeuristic)
94 }
95 add("--approximation", approximation.toString, "--approximationheuristic", heuristicName)
96 }
97 add("--dftfile", dftFilePath)
98 switch (objective) {
99 case FtAnalysisObjective.MTTF:
100 add("--expectedtime")
101 FtAnalysisObjective.TimeBound:
102 add("--timebound")
103 default:
104 throw new IllegalArgumentException("Unknown analysis objective: " + objective)
105 }
106 if (documentationLevel == DocumentationLevel.FULL) {
107 add("--verbose")
108 }
109 build
110 }
111
112 private def readOutput(InputStream inputStream, boolean printOutput) {
113 val bufferedReader = new BufferedReader(new InputStreamReader(inputStream))
114 try {
115 var String line
116 while ((line = bufferedReader.readLine) !== null) {
117 if (printOutput) {
118 println(line)
119 }
120 val matcher = RESULT_PATTERN.matcher(line)
121 if (matcher.find) {
122 try {
123 val single = matcher.group(SINGLE_RESULT_GROUP)
124 if (single !== null) {
125 val singleValue = Double.parseDouble(single)
126 return new ReliabilityResult.Solution(singleValue)
127 }
128 val lower = matcher.group(LOWER_BOUND_GROUP)
129 val upper = matcher.group(UPPER_BOUND_GROUP)
130 if (lower !== null && upper !== null) {
131 val lowerValue = Double.parseDouble(lower)
132 val upperValue = Double.parseDouble(upper)
133 return new ReliabilityResult.Solution(lowerValue, upperValue)
134 }
135 throw new StormDftException("Inconsistent stochastic solver output: " + line)
136 } catch (NumberFormatException e) {
137 throw new StormDftException("Malformatted number from stochastic solver.", e)
138 }
139 }
140 }
141 } finally {
142 bufferedReader.close
143 }
144 null
145 }
146
147 private def readError(InputStream inputStream, boolean printOutput) {
148 val bufferedReader = new BufferedReader(new InputStreamReader(inputStream))
149 try {
150 val lines = newArrayList
151 var String line
152 while ((line = bufferedReader.readLine) !== null) {
153 if (printOutput) {
154 System.err.println(line)
155 }
156 lines += line
157 }
158 lines.join("\n")
159 } finally {
160 bufferedReader.close
161 }
162 }
163
164 private def interpretExitStatus(int exitValue, String error) {
165 switch (exitValue) {
166 case STORM_GENERAL_ERROR:
167 throw new StormDftException("Storm error: " + error)
168 case STORM_TIMEOUT,
169 case SIGNAL_EXIT_VALUE_OFFSET + Signal.SIGXCPU.intValue:
170 ReliabilityResult.TIMEOUT
171 case STORM_MEMOUT,
172 case SIGNAL_EXIT_VALUE_OFFSET + Signal.SIGXFSZ.intValue:
173 ReliabilityResult.MEMOUT
174 default: {
175 if (exitValue > SIGNAL_EXIT_VALUE_OFFSET) {
176 val signalNumber = exitValue - SIGNAL_EXIT_VALUE_OFFSET
177 val signal = Signal.values.findFirst[intValue == signalNumber]
178 if (signal !== null) {
179 throw new StormDftException("Storm unexpectedly killed by signal " + signal + ": " + error)
180 }
181 }
182 throw new StormDftException("Storm unexpectedly exit with status " + exitValue + ": " + error)
183 }
184 }
185 }
186}
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}