2. 故障树最小割集求解
任务说明
给定一棵已构建的故障树(含顶事件、中间事件与底事件),使用下行法求解全部最小割集。输入采用结构化文本描述故障树逻辑关系,输出为按事件编号排序的最小割集列表。
故障树输入定义
故障树以如下格式描述:每行表示一个逻辑门,GATE 门编号 输出事件 门类型 输入事件列表。门类型仅支持AND与OR。底事件为叶子节点,不出现在任何门的输出位置。顶事件为第一个门(G1)的输出事件。
GATE G1 TOP AND M1 M2
GATE G2 M1 OR X1 X2
GATE G3 M2 OR X2 X3
对应故障树:TOP = M1 ∩ M2,M1 = X1 ∪ X2,M2 = X2 ∪ X3。底事件:X1, X2, X3。
下行法求解算法
下行法从顶事件开始,逐层向下:遇到OR门将输入事件纵向展开(各自成行),遇到AND门将输入事件横向扩展(同行追加)。处理完所有门后,每行是一个割集;删除包含其他割集的超集,剩余即为最小割集。
Python实现
def solve_minimal_cuts(gate_lines):
gates = {}
for line in gate_lines:
parts = line.strip().split()
if not parts or parts[0] != "GATE":
continue
_, gid, out, gtype, *inputs = parts
gates[gid] = {"out": out, "type": gtype, "inputs": inputs}
# 收集底事件(不出现在任何门输出中)
outputs = {g["out"] for g in gates.values()}
all_events = set()
for g in gates.values():
all_events.update(g["inputs"])
basic_events = all_events - outputs
# 下行法:从顶事件开始逐层替换
top_gate = "G1"
rows = [[top_gate]]
processed = set()
while True:
expanded = False
new_rows = []
for row in rows:
new_row = []
for item in row:
# 若item是门且未处理,则展开
if item in gates and item not in processed:
gate = gates[item]
if gate["type"] == "OR":
# OR门:纵向展开,每行保留其他项+单个输入
for inp in gate["inputs"]:
new_rows.append([x for x in row if x != item] + [inp])
else: # AND
# AND门:横向扩展,替换为所有输入
new_row.extend(gate["inputs"])
expanded = True
else:
new_row.append(item)
if not any(item in gates and item not in processed for item in row):
new_rows.append(new_row)
if not expanded:
break
rows = new_rows
processed.add(top_gate) # 简化处理:逐层标记已展开的门
# 重新检查哪些门已展开
processed = set()
for row in rows:
for item in row:
if item in gates:
processed.add(item)
# 若所有行都不含门,则结束
if all(all(item not in gates for item in row) for row in rows):
break
# 去重与删除超集
cut_sets = set()
for row in rows:
cut_sets.add(tuple(sorted(row)))
# 删除超集
minimal = []
for cs in sorted(cut_sets, key=lambda x: (len(x), x)):
if not any(set(cs) > set(other) for other in cut_sets if other != cs):
minimal.append(list(cs))
return minimal, sorted(basic_events)
# 输入数据
gate_lines = [
"GATE G1 TOP AND M1 M2",
"GATE G2 M1 OR X1 X2",
"GATE G3 M2 OR X2 X3"
]
cuts, basics = solve_minimal_cuts(gate_lines)
print("底事件:", basics)
print("最小割集:")
for c in cuts:
print("{" + ", ".join(c) + "}")
预期输出
底事件: ['X1', 'X2', 'X3']
最小割集:
{X1, X2}
{X2, X3}
推导:TOP = (X1∪X2) ∩ (X2∪X3) = (X1∩X2) ∪ (X1∩X3) ∪ (X2∩X2) ∪ (X2∩X3)。其中X2∩X2 = X2,但X2是{X1,X2}和{X2,X3}的子集,因此{X2}不是割集(因单事件无法同时满足两个AND分支)。实际最小割集为{X1,X2}与{X2,X3}。
验证方法
运行上述代码,观察输出是否与预期一致。判定标准:程序输出的最小割集与手工推导结果完全相同,且每个割集均为原故障树的割集(即割集中所有底事件同时发生时顶事件必然发生),且不存在任一割集是另一个割集的子集。
运行与验证
将代码保存为minimal_cuts.py,在Python 3环境中执行python minimal_cuts.py。程序输出底事件列表与全部最小割集。验证判定标准:输出结果与上述预期输出完全一致,且每个最小割集均满足割集定义(割集中所有底事件发生时顶事件必然发生),同时不存在任何割集是另一个割集的子集。