dft2hd2reliabilityr 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dft2hd2reliabilityr/FaultTreeLib.py +291 -0
- dft2hd2reliabilityr/FaultTreeRLib.py +617 -0
- dft2hd2reliabilityr/HasseDiagramLib.py +1390 -0
- dft2hd2reliabilityr/LogicDoorLib.py +505 -0
- dft2hd2reliabilityr/__init__.py +34 -0
- dft2hd2reliabilityr-0.2.0.dist-info/METADATA +137 -0
- dft2hd2reliabilityr-0.2.0.dist-info/RECORD +10 -0
- dft2hd2reliabilityr-0.2.0.dist-info/WHEEL +5 -0
- dft2hd2reliabilityr-0.2.0.dist-info/licenses/LICENSE +21 -0
- dft2hd2reliabilityr-0.2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,617 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Bibliothèques utiles
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
#import plotly.graph_objects as go
|
|
6
|
+
|
|
7
|
+
import sympy
|
|
8
|
+
# CORRECTION-04 : matplotlib/networkx importes paresseusement dans ViewGraph ([viz] extra).
|
|
9
|
+
import logging # CORRECTION-03
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
from .LogicDoorLib import * # CORRECTION-11 : package relatif
|
|
14
|
+
from .FaultTreeLib import * # CORRECTION-11 : package relatif
|
|
15
|
+
from .HasseDiagramLib import * # CORRECTION-11 : package relatif
|
|
16
|
+
|
|
17
|
+
"""
|
|
18
|
+
Construction de l'arbre de défaillance
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
FaultTreeRs={} # fault tree dictionary
|
|
22
|
+
class FaultTreeR: # fault tree class
|
|
23
|
+
NFaultTreeR=0 # The number of fault tree
|
|
24
|
+
def __init__(self,n,IndivReliabilityVal=[[1]],IndivReliabilityFunc=[One],t=[0],Option=1): # n: number of nodes
|
|
25
|
+
"""
|
|
26
|
+
The function takes in a number of components, a list of reliability values, a list of
|
|
27
|
+
reliability functions, a list of times, and an option.
|
|
28
|
+
|
|
29
|
+
The function then creates a number of nodes, a number of subtrees, a number of reliabilities, a
|
|
30
|
+
number of labels, a number of adjacency matrices, a number of reliability matrices, and a number
|
|
31
|
+
of index tables.
|
|
32
|
+
|
|
33
|
+
The function then returns the number of components, the number of nodes, the nodes, the
|
|
34
|
+
subtrees, the reliabilities, the labels, the adjacency matrices, the reliability matrices, and
|
|
35
|
+
the index tables.
|
|
36
|
+
|
|
37
|
+
:param n: number of nodes
|
|
38
|
+
:param IndivReliabilityVal: a list of lists of the individual reliabilities of the components
|
|
39
|
+
:param IndivReliabilityFunc: a list of functions that represent the reliability of each
|
|
40
|
+
component
|
|
41
|
+
:param t: time
|
|
42
|
+
:param Option: 1 for reliability values, 2 for reliability functions, defaults to 1 (optional)
|
|
43
|
+
"""
|
|
44
|
+
self.id=id(self)
|
|
45
|
+
FaultTreeRs[str(self.id)]=self
|
|
46
|
+
self.__class__.NFaultTreeR+=1
|
|
47
|
+
self.Option=Option
|
|
48
|
+
self.IndFiabVal=IndivReliabilityVal
|
|
49
|
+
self.IndFiabFunc=IndivReliabilityFunc
|
|
50
|
+
self.Time=t
|
|
51
|
+
if (self.Option==1):
|
|
52
|
+
self.NComponent=len(self.IndFiabVal) # The number of component(s) of the system
|
|
53
|
+
else:
|
|
54
|
+
self.NComponent=len(self.IndFiabFunc) # The number of component(s) of the system
|
|
55
|
+
#print("\n self.NComponent Start in FaultTreeR")
|
|
56
|
+
#print(self.NComponent)
|
|
57
|
+
self.NNode=n # The number of nodes of the fault tree
|
|
58
|
+
self.Node=[] # The list of nodes of the fault tree
|
|
59
|
+
self.SubTree={} # The dictionary of subtrees of the fault tree
|
|
60
|
+
|
|
61
|
+
for i in range(self.NNode): # The list of nodes of the fault tree
|
|
62
|
+
self.SubTree[i]=None # The dictionary of subtrees of the fault tree
|
|
63
|
+
|
|
64
|
+
self.Reliability={} # The dictionary of reliability of the fault tree
|
|
65
|
+
self.Label=[]
|
|
66
|
+
self.AdjMat={}#matlib.zeros((n, n))
|
|
67
|
+
self.RelMat=[[],[],[],[],[],[]]
|
|
68
|
+
#[[Door],[NodeIn],[NodeOut],[Orders],[Times],[IndicesPrincipal]]
|
|
69
|
+
self.IdxTable=[[],[],[]]
|
|
70
|
+
#[[NumRel],[Node i],[Node j]]
|
|
71
|
+
|
|
72
|
+
def __del__(self): # destructor
|
|
73
|
+
"""
|
|
74
|
+
The __del__ method is called when the instance is about to be destroyed
|
|
75
|
+
"""
|
|
76
|
+
self.__class__.NFaultTreeR-=1
|
|
77
|
+
|
|
78
|
+
def IdxNode(self,Indices=None): # Indices: list of indices of nodes
|
|
79
|
+
"""
|
|
80
|
+
It returns the index of the node in the list of nodes
|
|
81
|
+
|
|
82
|
+
:param Indices: The indices of the node to be found
|
|
83
|
+
:return: The index of the node in the list of nodes.
|
|
84
|
+
"""
|
|
85
|
+
res=None
|
|
86
|
+
if (Indices in self.Node):
|
|
87
|
+
res=0
|
|
88
|
+
while (self.Node[res]!=Indices):
|
|
89
|
+
res=res+1
|
|
90
|
+
return res
|
|
91
|
+
|
|
92
|
+
def InOrder2(self,xx=[1,3,2],yy=[1,2,30]): # xx: list of indices of nodes, yy: list of indices of nodes
|
|
93
|
+
"""
|
|
94
|
+
If the two lists are equal, then they are in order. Otherwise, if the first list is shorter than
|
|
95
|
+
the second, then the first list is in order.
|
|
96
|
+
|
|
97
|
+
:param xx: the first list of numbers
|
|
98
|
+
:param yy: the current state of the board
|
|
99
|
+
:return: True or False
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
Examples:
|
|
103
|
+
---------
|
|
104
|
+
|
|
105
|
+
>>> FaultTreeR.InOrder2(None, [1,3,2], [1,2,30])
|
|
106
|
+
True
|
|
107
|
+
"""
|
|
108
|
+
i=min(len(xx),len(yy))-1
|
|
109
|
+
while ((xx[i]==yy[i]) and (i>=0)):
|
|
110
|
+
#print((xx,yy))
|
|
111
|
+
i=i-1
|
|
112
|
+
if (i<0):
|
|
113
|
+
res=True
|
|
114
|
+
else:
|
|
115
|
+
res=(xx[i]<yy[i])
|
|
116
|
+
return res
|
|
117
|
+
|
|
118
|
+
"""
|
|
119
|
+
def InOrder2(self,xx=[1,3,2],yy=[1,2,30]):
|
|
120
|
+
res=True
|
|
121
|
+
i=0
|
|
122
|
+
while ((res==True) and (i<min(len(xx),len(yy)))):
|
|
123
|
+
#print((xx,yy))
|
|
124
|
+
res=(res and (xx[i]<=yy[i]))
|
|
125
|
+
i=i+1
|
|
126
|
+
return res
|
|
127
|
+
|
|
128
|
+
print(InOrder2())
|
|
129
|
+
"""
|
|
130
|
+
|
|
131
|
+
def Leaves(self): # Returns the list of leaves of the fault tree
|
|
132
|
+
"""
|
|
133
|
+
It returns the indices of the nodes that are leaves in the graph
|
|
134
|
+
:return: the leaves of the tree.
|
|
135
|
+
"""
|
|
136
|
+
res=[]
|
|
137
|
+
for j in range(len(self.AdjMat)):
|
|
138
|
+
Temp=0
|
|
139
|
+
for i in range(len(self.AdjMat)):
|
|
140
|
+
if (i!=j):
|
|
141
|
+
Temp+=self.AdjMat[i][j]
|
|
142
|
+
if (self.InOrder2(self.Node[i],self.Node[j])):
|
|
143
|
+
Temp+=1
|
|
144
|
+
if (Temp==0):#((Temp==0) and (self.RelMat[0][j]==1)):
|
|
145
|
+
res.append(j)
|
|
146
|
+
return res
|
|
147
|
+
|
|
148
|
+
def Root(self): # Returns the index of the root of the fault tree
|
|
149
|
+
"""
|
|
150
|
+
It returns the index of the root node of the tree
|
|
151
|
+
:return: The root node of the graph.
|
|
152
|
+
"""
|
|
153
|
+
res=[]
|
|
154
|
+
for i in self.AdjMat.keys():
|
|
155
|
+
Temp=0
|
|
156
|
+
for j in range(len(self.AdjMat)):
|
|
157
|
+
if (i!=j):
|
|
158
|
+
Temp+=self.AdjMat[i][j]
|
|
159
|
+
if (self.InOrder2(self.Node[i],self.Node[j])):
|
|
160
|
+
Temp+=1
|
|
161
|
+
if (Temp==0):#((Temp==0) and (self.RelMat[0][j]==1)):
|
|
162
|
+
res.append(i)
|
|
163
|
+
return res
|
|
164
|
+
|
|
165
|
+
def Update(self,ID_P=None): # Updates the adjacency matrix of the fault tree
|
|
166
|
+
"""
|
|
167
|
+
If the last entry in the RelMat is a valid entry, then add it to the Node list and the AdjMat.
|
|
168
|
+
|
|
169
|
+
CORRECTION-01b (cf. CORRECTIONS.md) : meme correction que FaultTree.Update —
|
|
170
|
+
``ID_P`` optionnel, defaut ``ID_G``, sinon ``NewRelation`` levait ``TypeError``.
|
|
171
|
+
"""
|
|
172
|
+
if ID_P is None: # CORRECTION-01b : generateur d'etiquettes par defaut
|
|
173
|
+
ID_P = ID_G
|
|
174
|
+
n=len(self.RelMat[0])
|
|
175
|
+
if (n>0):
|
|
176
|
+
Test=(len(self.Node)<=self.NNode-2)
|
|
177
|
+
Test=Test or ((self.RelMat[1][-1] in self.Node) and (self.RelMat[2][-1] in self.Node))
|
|
178
|
+
Test=Test or ((not(self.RelMat[1][-1] in self.Node) or not(self.RelMat[2][-1] in self.Node)) and (len(self.Node)<=self.NNode-1))
|
|
179
|
+
if not(Test): # If the last node is not a leaf
|
|
180
|
+
#print("Update Test No")
|
|
181
|
+
del(self.RelMat[0][-1])
|
|
182
|
+
del(self.RelMat[1][-1])
|
|
183
|
+
del(self.RelMat[2][-1])
|
|
184
|
+
del(self.RelMat[3][-1])
|
|
185
|
+
del(self.RelMat[4][-1])
|
|
186
|
+
del(self.RelMat[5][-1])
|
|
187
|
+
else: # If the last node is a leaf
|
|
188
|
+
if not(self.RelMat[1][-1] in self.Node): # If the last node is a leaf and the last node is not in the list of nodes
|
|
189
|
+
self.Node.append(self.RelMat[1][-1])
|
|
190
|
+
self.Label.append(ID_P(1))
|
|
191
|
+
for i in range(len(self.Node)-1):
|
|
192
|
+
self.AdjMat[i].append(0)
|
|
193
|
+
self.AdjMat[len(self.Node)-1]=[0 for i in range(len(self.Node))]
|
|
194
|
+
if not(self.RelMat[2][-1] in self.Node): # If the last node is a leaf and the last node is not in the list of nodes
|
|
195
|
+
self.Node.append(self.RelMat[2][-1])
|
|
196
|
+
self.Label.append(ID_P(self.RelMat[0][-1]))
|
|
197
|
+
for i in range(len(self.Node)-1): # If the last node is a leaf and the last node is not in the list of nodes
|
|
198
|
+
self.AdjMat[i].append(0)
|
|
199
|
+
self.AdjMat[len(self.Node)-1]=[0 for i in range(len(self.Node))]
|
|
200
|
+
if (self.RelMat[0][-1]>=0): # If the last node is a leaf and the last node is in the list of nodes
|
|
201
|
+
self.IdxTable[0].append(n-1)
|
|
202
|
+
self.IdxTable[1].append(self.IdxNode(self.RelMat[1][-1]))
|
|
203
|
+
self.IdxTable[2].append(self.IdxNode(self.RelMat[2][-1]))
|
|
204
|
+
self.AdjMat[self.IdxTable[1][-1]][self.IdxTable[2][-1]]=1
|
|
205
|
+
#print("Update Test Ok")
|
|
206
|
+
#print(self.Node)
|
|
207
|
+
|
|
208
|
+
def Sort(self): # Sorts the list of nodes of the fault tree
|
|
209
|
+
"""
|
|
210
|
+
It sorts the relations in the tree in a way that makes it easier to draw the tree
|
|
211
|
+
"""
|
|
212
|
+
Temp1=[]
|
|
213
|
+
Temp2=[]
|
|
214
|
+
for i in range(len(self.IdxTable[0])): # Sorts the list of indices of the nodes
|
|
215
|
+
j=0
|
|
216
|
+
for k in range(len(self.IdxTable[0])): # Sorts the list of indices of the nodes
|
|
217
|
+
#if (self.InOrder2(self.RelMat[2][k],self.RelMat[1][i]) and (self.IdxTable[2][k]!=self.IdxTable[1][i])):
|
|
218
|
+
Test=(self.AdjMat[self.IdxNode(self.RelMat[2][k])][self.IdxNode(self.RelMat[1][i])]==1)
|
|
219
|
+
Test=Test or (self.InOrder2(self.RelMat[2][k],self.RelMat[1][i]))
|
|
220
|
+
Test=Test and (self.IdxTable[2][k]!=self.IdxTable[1][i])
|
|
221
|
+
if Test:
|
|
222
|
+
j=j+1
|
|
223
|
+
while (j in Temp1):
|
|
224
|
+
j=j+1
|
|
225
|
+
Temp1.append(j)
|
|
226
|
+
Temp2.append(0)
|
|
227
|
+
for i in range(len(self.IdxTable[0])):
|
|
228
|
+
Temp2[int(Temp1[i])]=i
|
|
229
|
+
Temp3=[[],[],[]]
|
|
230
|
+
Temp4=[[],[],[],[],[],[]]
|
|
231
|
+
for i in range(len(self.IdxTable[0])):
|
|
232
|
+
Temp3[0].append(i)
|
|
233
|
+
Temp3[1].append(self.IdxTable[1][int(Temp2[i])])
|
|
234
|
+
Temp3[2].append(self.IdxTable[2][int(Temp2[i])])
|
|
235
|
+
Temp4[0].append(self.RelMat[0][int(Temp2[i])])
|
|
236
|
+
Temp4[1].append(self.RelMat[1][int(Temp2[i])])
|
|
237
|
+
Temp4[2].append(self.RelMat[2][int(Temp2[i])])
|
|
238
|
+
Temp4[3].append(self.RelMat[3][int(Temp2[i])])
|
|
239
|
+
Temp4[4].append(self.RelMat[4][int(Temp2[i])])
|
|
240
|
+
Temp4[5].append(self.RelMat[5][int(Temp2[i])])
|
|
241
|
+
self.IdxTable=Temp3.copy()
|
|
242
|
+
self.RelMat=Temp4.copy()
|
|
243
|
+
#print("\n Sort Called in FaultTreeR")
|
|
244
|
+
#print(self.RelMat)
|
|
245
|
+
|
|
246
|
+
def NewRelation(self,Port=1,IndicesIn=None,IndicesOut=None,Orders=None,Times=None,IndicesPrincipal=None): # Creates a new relation in the fault tree
|
|
247
|
+
"""
|
|
248
|
+
This function adds a new relation to the tree.
|
|
249
|
+
|
|
250
|
+
:param Port: The port number of the relation, defaults to 1 (optional)
|
|
251
|
+
:param IndicesIn: list of indices of the nodes that are the input to the relation
|
|
252
|
+
:param IndicesOut: list of indices of the output nodes
|
|
253
|
+
:param Orders: list of integers, each integer is the order of the relation
|
|
254
|
+
:param Times: list of times for each order
|
|
255
|
+
:param IndicesPrincipal: This is a list of indices of the nodes that are the principal nodes of
|
|
256
|
+
the relation
|
|
257
|
+
"""
|
|
258
|
+
if (IndicesIn!=None) and (IndicesOut!=None):
|
|
259
|
+
if (len(IndicesIn)<=self.NNode) and (len(IndicesOut)<=self.NNode):
|
|
260
|
+
self.RelMat[0].append(Port)
|
|
261
|
+
self.RelMat[1].append(IndicesIn)
|
|
262
|
+
self.RelMat[2].append(IndicesOut)
|
|
263
|
+
self.RelMat[3].append(Orders)
|
|
264
|
+
self.RelMat[4].append(Times)
|
|
265
|
+
self.RelMat[5].append(IndicesPrincipal)
|
|
266
|
+
#print("\n NewRelation Called in FaultTreeR")
|
|
267
|
+
#print(self.RelMat)
|
|
268
|
+
self.Update()
|
|
269
|
+
self.Sort()
|
|
270
|
+
#print(self.RelMat)
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
def AutoCompletion(self): # Automatically completes the fault tree
|
|
274
|
+
"""
|
|
275
|
+
For each node, if it is not the same as another node, and if it is in order with another node,
|
|
276
|
+
then add a new relation between the two nodes.
|
|
277
|
+
"""
|
|
278
|
+
nn=len(self.Node)
|
|
279
|
+
for i in range(nn):
|
|
280
|
+
#print("yeah !")
|
|
281
|
+
#print(self.Node[i])
|
|
282
|
+
for j in range(nn):
|
|
283
|
+
if (i!=j) and self.InOrder2(self.Node[i],self.Node[j]):
|
|
284
|
+
self.NewRelation(1,self.Node[i],self.Node[j],None,None,None)
|
|
285
|
+
"""
|
|
286
|
+
mm=self.NNode
|
|
287
|
+
for i in range(nn):
|
|
288
|
+
for j in range(mm):
|
|
289
|
+
Temp=[0 for k in range(mm)]
|
|
290
|
+
Temp[j]=1
|
|
291
|
+
if (self.InOrder2(Temp,self.Node[i])) and (Temp!=self.Node[i]):
|
|
292
|
+
if not(Temp in self.Node):
|
|
293
|
+
if (len(self.Node)==self.NNode):
|
|
294
|
+
self.NNode+=1
|
|
295
|
+
self.NewRelation(1,Temp,self.Node[i],None,None,None)
|
|
296
|
+
"""
|
|
297
|
+
|
|
298
|
+
def RecursiveStruturation(self): # Recursive structurer of the fault tree
|
|
299
|
+
"""
|
|
300
|
+
It takes a tree and creates a new tree for each node in the original tree.
|
|
301
|
+
"""
|
|
302
|
+
##self.AutoCompletion()
|
|
303
|
+
#print("\n RecursiveStruturation in FaultTreeR")
|
|
304
|
+
#print("\n Nodes in RecursiveStruturation in FaultTreeR")
|
|
305
|
+
#print(self.Node)
|
|
306
|
+
for i in range(len(self.IdxTable[0])): # For each node
|
|
307
|
+
Temp=self.IdxTable[2][i]
|
|
308
|
+
#print("\n AdjMat: ")
|
|
309
|
+
#print(self.AdjMat)
|
|
310
|
+
nSon=0
|
|
311
|
+
#print("\n Sons: ")
|
|
312
|
+
for j in range(len(self.IdxTable[0])): #in range(len(self.Node)):
|
|
313
|
+
if ((self.IdxTable[1][j]!=Temp) and (self.IdxTable[2][j]==Temp)):
|
|
314
|
+
nSon+=1#self.AdjMat[j][Temp]
|
|
315
|
+
#print((self.IdxTable[1][j],self.IdxTable[2][j]))
|
|
316
|
+
#print(nSon)
|
|
317
|
+
self.SubTree[Temp]=FaultTree(nSon+1) # Creates a new subtree with nSon+1 nodes
|
|
318
|
+
for j in range(len(self.IdxTable[0])):
|
|
319
|
+
if (self.IdxTable[2][j]==Temp):
|
|
320
|
+
Temp1=self.RelMat[0][self.IdxTable[0][j]]
|
|
321
|
+
Temp2=self.RelMat[1][self.IdxTable[0][j]]
|
|
322
|
+
Temp3=self.RelMat[2][self.IdxTable[0][j]]
|
|
323
|
+
Temp4=self.RelMat[3][self.IdxTable[0][j]]
|
|
324
|
+
Temp5=self.RelMat[4][self.IdxTable[0][j]]
|
|
325
|
+
Temp6=self.RelMat[5][self.IdxTable[0][j]]
|
|
326
|
+
self.SubTree[Temp].NewRelation(Temp1,Temp2,Temp3,Temp4,Temp5,Temp6)
|
|
327
|
+
#print("\n NewRelation ")
|
|
328
|
+
#print(Temp1,Temp2,Temp3,Temp4,Temp5,Temp6)
|
|
329
|
+
#print("SubTree's Nodes ")
|
|
330
|
+
#print(self.SubTree[Temp].Node)
|
|
331
|
+
|
|
332
|
+
def Generation(self): # Generates the fault tree
|
|
333
|
+
|
|
334
|
+
"""
|
|
335
|
+
The function takes a tree and returns a list of lists, where each list is a generation of the
|
|
336
|
+
tree
|
|
337
|
+
:return: a list of lists. Each list in the list is a generation.
|
|
338
|
+
"""
|
|
339
|
+
#print("\n Generation called in FaultTreeR")
|
|
340
|
+
Temp1={i:self.Node[i] for i in range(len(self.Node))} # Creates a dictionary with the nodes as keys and the indices as values
|
|
341
|
+
Temp2={}
|
|
342
|
+
res=[self.Leaves().copy()]
|
|
343
|
+
#print("\n New generation")
|
|
344
|
+
#print(res[-1])
|
|
345
|
+
for i in res[0]:
|
|
346
|
+
Temp2[i]=self.Node[i].copy()
|
|
347
|
+
del(Temp1[i])
|
|
348
|
+
while (Temp1!={}): # While there are nodes to be generated (i.e. there are nodes in Temp1)
|
|
349
|
+
Leaves=[]
|
|
350
|
+
for j in Temp1.keys():
|
|
351
|
+
Cond=True
|
|
352
|
+
for i in range(len(self.Node)):
|
|
353
|
+
if (((self.AdjMat[i][j]==1) or (self.InOrder2(self.Node[i],\
|
|
354
|
+
self.Node[j]))) and (i!=j)):
|
|
355
|
+
Cond=Cond and (i in Temp2.keys())
|
|
356
|
+
if Cond :
|
|
357
|
+
Leaves.append(j)
|
|
358
|
+
for k in Leaves: # For each leaf in Leaves
|
|
359
|
+
Temp2[k]=self.Node[k].copy()
|
|
360
|
+
del(Temp1[k])
|
|
361
|
+
res.append(Leaves)
|
|
362
|
+
#print("\n New generation")
|
|
363
|
+
#print(res[-1])
|
|
364
|
+
#print("\n All cuts generated")
|
|
365
|
+
return(res)
|
|
366
|
+
|
|
367
|
+
def RecursiveReliability(self): # Recursive reliability of the fault tree (not used)
|
|
368
|
+
"""
|
|
369
|
+
It computes the reliability of a system, given the reliability of its components.
|
|
370
|
+
"""
|
|
371
|
+
#print("\n RecursiveReliability called in FaultTreeR")
|
|
372
|
+
self.RecursiveStruturation()
|
|
373
|
+
Temp=self.Generation()
|
|
374
|
+
#print("\n All generations")
|
|
375
|
+
#print(Temp)
|
|
376
|
+
|
|
377
|
+
def LeafReliability(Generation,i,Option): # Recursive reliability of the leaf i in the generation Generation (not used)
|
|
378
|
+
"""
|
|
379
|
+
It takes a list of nodes (Generation), an index (i) and an option (Option) and returns a
|
|
380
|
+
dictionary of the form {node: {0: [list of symbols], 1: [list of reliability values]}}
|
|
381
|
+
|
|
382
|
+
:param Generation: a list of the nodes in the current generation
|
|
383
|
+
:param i: the index of the node in the generation
|
|
384
|
+
:param Option: 1 for reliability values, 2 for reliability functions
|
|
385
|
+
"""
|
|
386
|
+
#print("\n LeafReliability called in DefautTreeR")
|
|
387
|
+
R=[]
|
|
388
|
+
R2=[]
|
|
389
|
+
for j in range(self.NComponent): # For each component
|
|
390
|
+
if (self.Node[Generation[i]][j]==1):
|
|
391
|
+
R.append(sympy.Symbol("R"+str(j)))
|
|
392
|
+
if (Option==1): # If the option is 1, the reliability is the probability of the component
|
|
393
|
+
"""
|
|
394
|
+
print("\n self.NComponent")
|
|
395
|
+
print(self.NComponent)
|
|
396
|
+
print("\n Le node 1" )
|
|
397
|
+
print(self.Node[Genreration[i]])
|
|
398
|
+
"""
|
|
399
|
+
|
|
400
|
+
R2.append([self.IndFiabVal[j][k] for k in range(len(self.Time))]) # The reliability is the probability of the component
|
|
401
|
+
else:
|
|
402
|
+
"""
|
|
403
|
+
print("\n self.NComponent")
|
|
404
|
+
print(self.NComponent)
|
|
405
|
+
print("\n Le node 2" )
|
|
406
|
+
print(self.Node[Genreration[i]])
|
|
407
|
+
"""
|
|
408
|
+
#print("\ Reliability steps")
|
|
409
|
+
#print([len(self.IndFiabFunc),j])
|
|
410
|
+
R2.append([self.IndFiabFunc[j](self.Time[k]) for k in range(len(self.Time))])
|
|
411
|
+
self.Reliability[Generation[i]]={} # Creates a new dictionary for the reliability of the node in the generation Generation
|
|
412
|
+
#self.Reliability[Genreration[i]][0]=sympy.Symbol("R"+str(Genreration[i]))
|
|
413
|
+
self.Reliability[Generation[i]][0]=R # The reliability is the probability of the component
|
|
414
|
+
#self.Reliability[Genreration[i]][1]=[self.IndFiabVal[i][j] for j in range(len(self.Time))]
|
|
415
|
+
self.Reliability[Generation[i]][1]=R2 # The reliability is the probability of the component
|
|
416
|
+
#self.Reliability[Genreration[i]][1]=[self.IndFiabFunc[i](self.Time[j]) for j in range(len(self.Time))]
|
|
417
|
+
self.Reliability[Generation[i]][1]=R2 # The reliability is the probability of the component
|
|
418
|
+
#print(self.Reliability[Genreration[i]][0])
|
|
419
|
+
#print(self.Reliability[Genreration[i]][1])
|
|
420
|
+
#print(R)
|
|
421
|
+
#print(R2)
|
|
422
|
+
|
|
423
|
+
def BranchReliability(Generations,i,Option): # Recursive reliability of the branch i in the generations Generations (not used)
|
|
424
|
+
"""
|
|
425
|
+
It computes the reliability of a node of the tree, by computing the reliability of the
|
|
426
|
+
sub-tree it is connected to
|
|
427
|
+
|
|
428
|
+
:param Generations: a list of lists of integers. Each list of integers is a generation of the
|
|
429
|
+
tree
|
|
430
|
+
:param i: the index of the generation
|
|
431
|
+
:param Option: 1 for reliability values, 2 for reliability functions
|
|
432
|
+
"""
|
|
433
|
+
#print("\n BranchReliability called in DefautTreeR")
|
|
434
|
+
for k in range(len(Generations[i])): # For each generation in the branch i
|
|
435
|
+
j=Generations[i][k] # j is the index of the generation
|
|
436
|
+
if (self.SubTree[j]==None): # If the generation is a leaf
|
|
437
|
+
LeafReliability(Generations[i],k,Option) # Recursive reliability of the leaf k in the generation j
|
|
438
|
+
#print("Here") # If the generation is a leaf
|
|
439
|
+
#print(j)
|
|
440
|
+
#print(self.Reliability[j])
|
|
441
|
+
#print("Ok")
|
|
442
|
+
|
|
443
|
+
else: # If the generation is a branch
|
|
444
|
+
Temp1=self.SubTree[j] # Temp1 is the subtree of the branch j
|
|
445
|
+
#print("\n The subTree "+str([i,j]))
|
|
446
|
+
#print(Temp1.RelMat)
|
|
447
|
+
#print(Temp1.Node)
|
|
448
|
+
#print([Temp1.NNode,len(Temp1.Node)])
|
|
449
|
+
Temp2=[]
|
|
450
|
+
Temp3=[]
|
|
451
|
+
Temp4=[]
|
|
452
|
+
#print("\n Temp1.NNode 1")
|
|
453
|
+
#print(Temp1.NNode)
|
|
454
|
+
|
|
455
|
+
for kk in range(Temp1.NNode): # For each node in the subtree of the branch j
|
|
456
|
+
if (Temp1.Node[kk]!=self.Node[j]): # If the node is not the same as the branch j
|
|
457
|
+
Temp2=[] # Temp2 is the list of the nodes of the subtree of the branch j
|
|
458
|
+
Temp3=[] # Temp3 is the list of the reliability of the nodes of the subtree of the branch j
|
|
459
|
+
Temp4=[] # Temp4 is the list of the reliability of the nodes of the subtree of the branch j
|
|
460
|
+
"""
|
|
461
|
+
print("\n Les fiabilités connues :")
|
|
462
|
+
print(self.Reliability)
|
|
463
|
+
|
|
464
|
+
print("\n Le node 3")
|
|
465
|
+
print(Temp1.Node[kk])
|
|
466
|
+
"""
|
|
467
|
+
|
|
468
|
+
for l in range(len(Temp1.Node[kk])):#range(self.NComponent):
|
|
469
|
+
if (Temp1.Node[kk][l]==1): # If the component is active in the node
|
|
470
|
+
Temp2.append(l) # The component is added to the list of the nodes of the subtree of the branch j
|
|
471
|
+
if (l<self.NComponent): # If the component is active in the node
|
|
472
|
+
Temp3.append(sympy.Symbol("R"+str(l))) # The reliability is the probability of the component
|
|
473
|
+
if (Option==1):
|
|
474
|
+
#print("\n Here 1 !")
|
|
475
|
+
#print(self.IndFiabVal[l])
|
|
476
|
+
Temp4.append([self.IndFiabVal[l][kkk] for kkk in range(len(self.Time))])
|
|
477
|
+
else:
|
|
478
|
+
#print("\n Here 2 !")
|
|
479
|
+
#print(self.IndFiabFunc[l])
|
|
480
|
+
Temp4.append([self.IndFiabFunc[l](self.Time[kkk]) for kkk in range(len(self.Time))])
|
|
481
|
+
else:
|
|
482
|
+
Node=[0 for kkk in range(len(Temp1.Node[kk]))]
|
|
483
|
+
Node[l]=1
|
|
484
|
+
ll=self.IdxNode(Node)
|
|
485
|
+
#print("\n Les fiabilités connues :")
|
|
486
|
+
#print(self.Reliability)
|
|
487
|
+
#print("\n Here 30 !")
|
|
488
|
+
#print(ll)
|
|
489
|
+
#print(self.Reliability[ll])
|
|
490
|
+
#print("Ok")
|
|
491
|
+
|
|
492
|
+
Temp3.append(self.Reliability[ll][0][0])
|
|
493
|
+
Temp4.append(self.Reliability[ll][1][0])
|
|
494
|
+
|
|
495
|
+
#print(Temp3)
|
|
496
|
+
#print("\n Index 1")
|
|
497
|
+
#print(Temp2)
|
|
498
|
+
#print(Temp4)
|
|
499
|
+
#print(k)
|
|
500
|
+
#print(Temp2)
|
|
501
|
+
Temp5=self.Time
|
|
502
|
+
#print("\n Here 3 !")
|
|
503
|
+
#print(Temp2)
|
|
504
|
+
#print(Temp4)
|
|
505
|
+
#print(len(Temp4))
|
|
506
|
+
#print((Temp1,Temp2,Temp3,Temp4,None,Temp5,1))
|
|
507
|
+
logger.debug("BranchReliability: computing node %s", j) # CORRECTION-03
|
|
508
|
+
MyUpHasseDiagram=UpHasseDiagram(Temp1,Temp2,Temp3,Temp4,None,Temp5,1) # The UpHasseDiagram of the subtree of the branch j is created
|
|
509
|
+
##(Tree=FaultTree(2),IndivIndex=[0],IndivLabel=[0],IndivReliabilityVal=[[1]],IndivReliabilityFunc=[One],t=[0],Option=1)
|
|
510
|
+
|
|
511
|
+
MyPolyFiab=MyUpHasseDiagram.GetPolyFiab() # The polynomial of the reliability of the subtree of the branch j is computed
|
|
512
|
+
|
|
513
|
+
self.Reliability[j]={} # The reliability of the branch j is initialized
|
|
514
|
+
self.Reliability[j][0]=[MyPolyFiab[0]] # The reliability of the branch j is initialized
|
|
515
|
+
self.Reliability[j][1]=[MyPolyFiab[1]]
|
|
516
|
+
#print("\n Current Reliability :")
|
|
517
|
+
#print(self.Reliability[j][1])
|
|
518
|
+
#print("Here")
|
|
519
|
+
#print(j)
|
|
520
|
+
#print(self.Reliability[j])
|
|
521
|
+
#print("Ok")
|
|
522
|
+
|
|
523
|
+
for i in range(len(Temp[0])): # For each branch in the tree
|
|
524
|
+
LeafReliability(Temp[0],i,self.Option) # Recursive reliability of the branch i in the tree
|
|
525
|
+
#print(i)
|
|
526
|
+
|
|
527
|
+
if (len(Temp)>1): # If the tree is not a leaf
|
|
528
|
+
for i in range(1,len(Temp)): # For each branch in the tree
|
|
529
|
+
#print("In")
|
|
530
|
+
#print(i)
|
|
531
|
+
BranchReliability(Temp,i,self.Option) # Recursive reliability of the branch i in the tree
|
|
532
|
+
#print("Out")
|
|
533
|
+
#print(i)
|
|
534
|
+
|
|
535
|
+
res=[] # The list of the reliability of the tree is initialized
|
|
536
|
+
for j in Temp[-1]:
|
|
537
|
+
res.append(self.Reliability[j])
|
|
538
|
+
|
|
539
|
+
#print("\n In BranchReliability ")
|
|
540
|
+
#print("\n Reliability polynomial R= ")
|
|
541
|
+
#print(res)
|
|
542
|
+
return [self.Time,res]
|
|
543
|
+
|
|
544
|
+
def ViewGraph(self,ID_P,Dir=None): # View the tree in a graph
|
|
545
|
+
"""
|
|
546
|
+
It takes a list of nodes and a list of edges, and draws a graph
|
|
547
|
+
|
|
548
|
+
:param ID_P: The ID of the parent node
|
|
549
|
+
:param Dir: The directory where the graph will be saved
|
|
550
|
+
"""
|
|
551
|
+
# CORRECTION-04 : import paresseux de la pile graphique optionnelle
|
|
552
|
+
try:
|
|
553
|
+
import networkx as nx
|
|
554
|
+
import matplotlib.pyplot as plt
|
|
555
|
+
except ImportError as exc:
|
|
556
|
+
raise ImportError(
|
|
557
|
+
"ViewGraph requires the optional visualization extras: "
|
|
558
|
+
"pip install matplotlib networkx"
|
|
559
|
+
) from exc
|
|
560
|
+
self.AutoCompletion() # The tree is automatically completed
|
|
561
|
+
G=nx.DiGraph() # The graph is initialized
|
|
562
|
+
GNode={} # The graph is initialized
|
|
563
|
+
nn=len(self.Node) # The number of branches is computed
|
|
564
|
+
for i in self.AdjMat.keys(): # For each branch in the tree
|
|
565
|
+
for j in range(len(self.AdjMat[i])): # For each node in the branch
|
|
566
|
+
if (self.AdjMat[i][j]==1): # If the node is active
|
|
567
|
+
GNode[nn-1-self.IdxNode(self.Node[i])]=str(nn-1-self.IdxNode(self.Node[i]))+':'+self.Label[i]
|
|
568
|
+
GNode[nn-1-self.IdxNode(self.Node[j])]=str(nn-1-self.IdxNode(self.Node[j]))+':'+self.Label[j]
|
|
569
|
+
G.add_edge(GNode[nn-1-self.IdxNode(self.Node[i])],GNode[nn-1-self.IdxNode(self.Node[j])])
|
|
570
|
+
#G.add_edge(str(nn-1-self.IdxNode(self.Node[i]))+':'+self.Label[i],str(nn-1-self.IdxNode(self.Node[j]))+':'+self.Label[j])
|
|
571
|
+
#G.add_edge(str(self.Node[j]),str(self.Node[i]))
|
|
572
|
+
#CompleteNode=self.Node.copy()
|
|
573
|
+
|
|
574
|
+
mm=nn # The number of nodes is computed
|
|
575
|
+
for i in range(nn): # For each node in the tree
|
|
576
|
+
#print("yeah !")
|
|
577
|
+
#print(self.Node[i])
|
|
578
|
+
for j in range(nn): # For each node in the tree
|
|
579
|
+
if (i!=j) and self.InOrder2(self.Node[i],self.Node[j]):
|
|
580
|
+
G.add_edge(GNode[nn-1-self.IdxNode(self.Node[i])],GNode[nn-1-self.IdxNode(self.Node[j])])
|
|
581
|
+
for j in range(self.NNode): # For each node in the tree
|
|
582
|
+
Temp=[0 for k in range(self.NNode)]
|
|
583
|
+
Temp[j]=1
|
|
584
|
+
if (self.InOrder2(Temp,self.Node[i])) and (Temp!=self.Node[i]):
|
|
585
|
+
#print(Temp)
|
|
586
|
+
if not(Temp in self.Node):
|
|
587
|
+
GNode[mm]=str(mm)+':'+ID_P(1)
|
|
588
|
+
G.add_edge(GNode[mm],GNode[nn-1-self.IdxNode(self.Node[i])])
|
|
589
|
+
mm+=1
|
|
590
|
+
#G.add_edge(str(self.Node[i]),str(Temp))
|
|
591
|
+
#CompleteNode.append(Temp)
|
|
592
|
+
|
|
593
|
+
#print(G.adj)
|
|
594
|
+
#fig=plt.figure(figsize=(5,5))
|
|
595
|
+
plt.subplots(figsize=(10, 10)) # The graph is displayed
|
|
596
|
+
plt.clf() # The graph is cleared
|
|
597
|
+
nx.draw_networkx(G,pos=nx.circular_layout(G),node_size=(10**4)/2) # The graph is displayed
|
|
598
|
+
#nx.draw(G)
|
|
599
|
+
#nx.draw(G,pos=nx.circular_layout(G),node_color='r',edge_color='b')
|
|
600
|
+
plt.axis('off') # The graph is not displayed
|
|
601
|
+
#plt.grid(False)
|
|
602
|
+
if (Dir!=None): # If a directory is given
|
|
603
|
+
plt.savefig(Dir+"AD.png") # The graph is saved
|
|
604
|
+
plt.savefig(Dir+"AD.pdf",format="pdf") # The graph is saved
|
|
605
|
+
plt.show() # The graph is displayed
|
|
606
|
+
|
|
607
|
+
"""
|
|
608
|
+
Dir="E:/Pedagogie/Encadrement/EncadrementEnsai/MasterRThese/20192020/TadieBenjaulys/"
|
|
609
|
+
|
|
610
|
+
MyTree=FaultTreeR(3,[[1],[1]],[One,One],[0],1)
|
|
611
|
+
MyTree.NewRelation(3,[1,1,0],[0,0,1])
|
|
612
|
+
print(MyTree.RecursiveReliability())
|
|
613
|
+
#MyTree.ViewGraph(Dir)
|
|
614
|
+
|
|
615
|
+
#MyUpHasseDiagram=UpHasseDiagram(MyTree,[0,1],[[1],[1]],[One,One],[0],1)
|
|
616
|
+
|
|
617
|
+
"""
|