I've made a programm that return a "belonging table" DataFrame of edges of Multigraph that models a Electrical Grid. each line is a a path between a load and a source, the columns are the names of the lines that connect the load to the source.
The program I wrote generates an output df that looks like this one, but much larger.
import pandas as pd
belonging = pd.DataFrame({'A': {0: False, 1: False, 2: True, 3: True},
'B': {0: True, 1: True, 2: False, 3: False},
'C': {0: False, 1: True, 2: False, 3: True},
'D': {0: True, 1: False, 2: True, 3: False}})
>>>
A B C D E F
0 False False True False True True
1 False False True True False True
2 True True False False True True
3 True True False True False True
Now I need to generate a "failure modes" table, that give an output that would be like this:
result = pd.DataFrame(
{'Failure Modes' : {0: 'F', 1: 'A // C', 2: "B // C", 3: "D // E"},
'Order of Failure' : {0: 1, 1: 2, 2: 2, 3: 2}
}
)
>>>
Failure Modes Order of Failure
0 F 1
1 A // C 2
2 B // C 2
3 D // E 2
The failure Modes table is contructed from the boolean value of the columns, if all the items in a column are true, than that is a first order of faliure. The second order of faliure tries to check for the truth values of every two columns, except those already found to be a first order.
And so on the nth-order. with n <= len(belonging.columns)
.
Describing it makes it sound simpler to me than I can write in code. Thank you in advance.
Using the soluting presented by @Cammeron Riddel and @Mozway I got to this solution to the problem:
bt = pd.DataFrame({
'a': [False, False, True,True],
'b': [False, False, True, True],
'c': [True, True, False, False],
'd': [False, True, False, True],
'e': [True, False, True, False],
'f': [True, True, True, True],
})
# bt = belonging_table
def power_set(entities):
for i in range(len(entities)+1):
yield from combinations(entities, r=i)
seen = defaultdict(set)
failures = pd.DataFrame(columns=['Oder'])
for columns in power_set(bt.columns):
order = len(columns)
last_order = order - 1
seen[order] = seen[order].union(seen[last_order])
if len(columns) == 0 or set(columns).intersection(seen[last_order]):
continue
if logical_xor.reduce(bt[list(columns)], axis=1).all():
failures.loc['//'.join([str(edge) for edge in columns])] = order
seen[order] = seen[order].union(columns)
if len(seen[order]) == len(bt.columns):
break
failures
Order
f 1
a//c 2
b//c 2
d//e 2
This changes where made because of errors found in larger origin destiny pairs with up too 500 different paths