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.
@@ -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
+ """