基于CList链表类的故障树分析算法的实现

1  引言

故障树是指将要诊断的设备故障事件作为第一级;将导致该故障发生的所有原因并列作为第二级;然后用适当的逻辑门把它们与设备故障事件连接起来;再将第二级各故障事件发生的原因分别并列在第二级故障事件下面作为第三级;按照此方法,一级级往下,直到把最基本的不能再分解的原因都分析出来,得到的这样一张逻辑图称为故障树

故障树分析包括定性分析和定量分析。定性分折的主要目的是寻找导致与系统有关的不希望事件发生的原因和原因的组合,即寻找导致顶事件发生的所有故障模式。定量分析的主要目的是当给定所有底事件发生的概率时,求出顶事件发生的概率及其他定量指标。

 定性分析算法的实现

1为一个示例故障树,基本事件X1~X5别代表故障1~故障5

基于CList链表类的故障树分析算法的实现

示例故障树

定性分析重点就是求出故障树的MCS ,得到导致顶层故障发生的各种故障模式。求MCS通常有:求割集有下行法、上行法BDD等。

下面采用MFC中的CList链表,结合环形数组来实现下行法。CListMFC中一个链表类,链表节点可以存储各种数据结构,且具有丰富的链表操作函数,诸如本算法用到的GetAt()RemoveAt()InsertBefore()FindIndex()GetCount()IsEmpty()等,使用非常方便,省去了自己定义链表以及链表操作函数的复杂过程。

首先定义个故障树节点结构体FtNode,包含了故障树节点的各种信息,该结构体代表各节点信息,并存储在CList链表中。

typedef  struct  FtNode

{

        int GateType; //门类型

        int ChildrenNum; //孩子节点数

        double cf; //基本事件发生概率

        CString NodeDescription; //故障事实描述,如下文

                                                 //的“X1故障”

        ……//包含其它的信息

}

定义一个存放按层次遍历得到的故障树各节点的CList链表:CList<FtNode, FtNode&> FtList存储形式如图2所示。

基于CList链表类的故障树分析算法的实现

节点在CList中的存储

       接着以数组形式定义200CList链表(可按实际故障树大小来调整改大小):

 CList<FtNode, FtNode&> CutSet[200]

      求解过程的基本思路是:首先FtList中的T节点添加到CutSet[0],用counter计数当前已经使用过的数组数量,用ijl控制三层for循环,外层循环i遍历整个数组,中层循环j遍历i为某个特定k值时的CutSet[k]链表中各个节点,内层l循环扫描FtList链表以查找子节点。从T开始扫描分析,如遇到与门,则删除该节点,用CopyList函数复制已删除该节点的CutSet[k]CutSet[counter+1],同时添加该节点的所有子节点(在FtList链表中扫描出子节点)到链表CutSet[counter+1]中;如果遇到或门,且子节点数为ChildrenNum时,则在CutSet[k]中删除该节点,并复制ChildrenNum个已删除该节点的CutSet[k],分别放在CutSet[counter+1]CutSet[counter+2]、…、CutSet[counter+ChildrenNum]中,在i递增到这些counter+1counter+2、…、counter+ ChildrenNum的位置时,再对新的链表分析。前5次循环过程CutSet[i]分布情况如图3所示,白色节点表示分析完毕,或已经是底层基本事件(不需要继续分析基本事件),浅色表示正在分析的节点,深色表示未分析的节点。

        

5步的割集求解过程

整个故障树分析完成后,将得到类似CutSet[4]所示的每个节点都由基本事件组成的链表,这种链表存放的即为一个割集,分析完毕的链表如CutSet[0]~CutSet[3],得到释放。如果到CutSet[200],已经无链表可用时,但还未得到所有割集时,可使外层循环i = i  200来构造一个数组环来循环利用前面释放的链表。这样200个链表经实际运行估计,可以得到割集数大于100个,基本适应故障诊断中任何大型故障树。

上述过程的程序算法描述如下:

//FtListT节点添加到CutSet[0],作为扫描的入口

CutSet[0].AddTail(FtList.GetHead());

counter = 0;//记录使用的最大数组下标

for (int i=0; i<200; i++)

{

if(!CutSet[i].isEmpty())//链表不为空则进行下面操作

for(int j=0; j<CutSet[i].GetCount(); j++)

{

   //得到该节点第一个孩子节点在FtList中的位置

                int c = GetFirstChild();

                POSITION p = CutSet[i].FindIndex(j);

                switch(CutSet[i].GetAt(p).GateType)

                {

                case 0: //0为与门

                          //删除该节点,后面将用其子节点代替

                          CutSet[i].ReMoveAt(p);

                 //下面为复制链表

                 CutSet[++counter]= CopyList(CutSet[i]);

for(int l=c; l<=ChildrenNum; l++)

FtList中从c开始到c+ ChildrenNum处的子节点分别添加到CutSet[++counter]中从 p开始到p+ ChildrenNum位置处;

//删除分析过的链表

CutSet[i].RemoveAll();

break;

                case 1: //1为或门

                          ……

                          break;

                default: //叶子节点则不作处理

                          break;

        }

        if(i>200 && 未分析完全)

            i = i  200;

}

这样得到的链表中,只要不为NULL,则最终存放的是一个割集,对所有链表进行一次是否为NULL的扫描判断,就可以提取出割集。对于本示例故障树,可以得到割集如下:{X1X2}{X1X3X4}{X2X3X5}{X2X3X4}{X3X4X5}{X3X4}。然后利用程序判断割集之间是否存在包含与被包含关系,丢弃包含了其它割集的割集,例如割集{X1X3X4}{X2X3X4}{X3X4X5}包含了割集{X3X4},因此丢弃这三个割集,剩下的{X1X2}{X2X3X5}{X3X4}组成了该故障树的MCS

 定量分析算法的实现

3.1 顶事件发生概率

      当知道各基本事件的发生概率,各基本事件又是独立事件时,就可以计算顶上事件的发生概率。目前,计算顶上事件发生概率的方法有若干种,下面介绍一种工程上的近似计算。

Fs表示顶事件发生概率,n表示基本事件的个数,m表示MCS个数,Fi表示MCS概率积,即MCS中,基本事件发生概率的乘积。工程上近似计算顶事件发生概率如公式为:

基于CList链表类的故障树分析算法的实现

为利用求得的MCS实现,先将得到的m个MCS,分别存放在CutSet[0]~CutSet[m-1]中。

第一步:先求各个割集积Fi,分别存放在数组FI[i]中,并累加到double  F中,程序算法如下:

for (int i=0; i<m; i++)

{

FI[i] = 1.0;

for(int j; j<CutSet[j].GetCount(); j++)

{

POSITION p = CutSet[i].FindIndex(j);

       FI[j] *= CutSet[i].GetAt(p).cf;

}

F += FI[i];

}

第二步:求割集交叉积FiFj,并累加到double FF,程序算法如下:

FF = 0;

for (int i=0; i<m; i++)

{

         for(int j=i+1; j<m; j++)

                   FF = FF +FI[i]*FI[j];

}

第三步:求差FS = F  FF,得到顶事件发生概率。

3.2 基本事件的重要度

3.2.1 概率重要度

如果进一步考虑基本事件发生概率的变化会给顶上事件发生概率以多大影响,就要分析基本事件的概率重要度。利用顶事件发生概率Fs函数是一个多重线性函数这一性质,只要对自变量qi求一次偏导数,就可得出该基本事件的概率重要度系数,公式如下

 

基于CList链表类的故障树分析算法的实现

第一步:当i=k时,判断CutSet[k]中有无Xi,如有,则先去除Xi节点,如没有,则删除此链表(偏导为0),程序算法如下:

for(int i=0; i<m; i++)

{

        for(int j; j<CutSet[j].GetCount(); j++)

        {

                   POSITION p = CutSet[i].FindIndex(j);

                   if(Xi == CutSet[i].GetAt(p))

                          CutSet[i].ReMoveAt(p);

        }

        if(如果CutSet[j]不包含Xi)

                   CutSet[i].ReMoveAll();

}

第二步:调用2.1节中的求顶事件发生概率的程序算法,得到概率重要度Ip(i)

3.2.2 结构重要度

底事件结构重要度从故障树结构的角度反映了各底事件在故障树中的重要程度,是从事故树结构上入手分析各基本事件的重要程度,概率重要度有这样一个重要性质:当假定所有基本事件发生概率均为0.5时,概率重要度系数就等于结构重要度系数。因此,令FtNode中的所有cf值为0.5,利用2.2.1节概率重要度中的程序算法就可以得到各基本事件的结构重要度。

3.2.3 临界重要度

一般情况,减少概率大的基本事件的概率要比减少概率小的容易,而概率重要度系数并未反映这一事实,因此,它不是从本质上反映各基本事件在事故树中的重要程度。而临界重要度系数Ci则是从敏感度和概率双重角度衡量各基本事件的重要度标准,它与概率重要度系数的关系是:

基于CList链表类的故障树分析算法的实现

利用2.1节求顶事件发生概率和2.2.1节求概率重要度的算法,再乘上因子qi/Fs就得到各基本事件的临界重要度。

 示例故障树分析结果

4是在VC++6.0集成开发环境下采用上述基于CList链表的算法编写的故障树分析程序运行结果。对文章中的故障树各种分析结果在界面上均有显示。所有故障事实存放在数据库中,并采用“F”开头的编号表示,F000000004表示X1故障、F000000006表示X2故障、F000000009表示X3故障、F000000010表示X4故障、F000000011表示X5故障,以 C”开头的编号表示最小割集,此故障树一共得到3MCS{X1X2}{X2X3X5}{X3X4},如界面中的表1所示。基本事件的三种重要度分别如界面中的表2所示,并且以曲线形式在底部的图形控件中显示,其中,发生概率和概率重要度的值偏小,为便于观察,将它们的曲线放大了10倍。

基于CList链表类的故障树分析算法的实现

示例故障树分析结果

各基本事件的发生概率排序和根据本软件分析结果按各重要度排序分别如下:

1)发生概率:  X5>X4>X3=X2>X1

2)概率重要度:X3>X4=X1>X2>X5

3)结构重要度:X2=X3>X4=X1>X5

4)临界重要度:X3>X4>X2>X1>X5

从概率重要度系数可以看出这样的事实:一个基本事件的概率重要度如何,并不取决于它本身的概率值大小,而取决于它所在MCS中其他基本事件的概率积的大小及它在各个MCS中重复出现的次数。

在结构重要度上,基本事件X2X3X4X1分别处于同样重要的位置,X5在系统中的结构位置对系统的影响是最小的。

与概率重要度相比,基本事件X1的重要程度下降了,这是因为它的发生概率最低。基本事件X3最重要,这不仅是因为它敏感度最大,而且它本身的概率值也较大。

综上述,对于本故障树体现的系统,因该加强X3部件的检修,减少系统的发生故障的概率。

5          

由于故障树在数据结构上表现的是一种树形结构,其分支和层数可以任意数目,加上故障树中还存在各种门,最基本的包含了“与门”和“非门”,因此,对故障树进行分析的程序算法是一个复杂的过程,文章在VC++6.0集成环境下,利用MFC中已有的CList链表类的优势,结合数组环,很好的实现了最小割集的求解,以及顶事件发生概率、基本事件的重要度等的求解,程序对示例故障树进行分析,结果表明程序的有效性和可靠性。

 

基于CList链表类的故障树分析算法的实现

基于CList链表类的故障树分析算法的实现

转载自http://blog.csdn.net/andy8205/article/details/1724625