利用Python实现NFA到DFA的转化(子集法)

一.不确定有穷自动机转换成确定的有穷自动机(NFA转DFA)

1.代码实现

__author__='PythonStriker'
global NFA_StautsMatrix,DFA_StautsMatrix,StartWorld,EndWorld,\
    StatusNumber,EnterNumber,EnterWorld,NFA_StatusWorld,DFA_StatusWrold
EnterWorld = []                                                                    #输入状态
NFA_StatusWorld = []                                                               #NFA有穷状态集
DFA_StatusWrold = []                                                               #DFA有穷状态集

def main():
    EndList = []
    global NFA_StautsMatrix, DFA_StautsMatrix, StartWorld, EndWorld, \
        StatusNumber, EnterNumber, EnterWorld, NFA_StatusWorld,DFA_StatusWrold
    StartWorld = input("输入开始状态:")
    EndWorld = input("输入结束状态:")
    StatusNumber = int(input("输入状态个数:"))
    EnterNumber = int(input("状态机输入个数:"))
    print("输入不确定有穷状态机转换表:")
    NFA_StautsMatrix = [[] for _ in range(0,StatusNumber + 1)]                      #NFA状态转换表
    for row in range(0,StatusNumber + 1):                                          #存入状态转换表
        line  = input().split(' ')
        for column in range(len(line)):
            NFA_StautsMatrix[row].append(line[column])

    for enter in NFA_StautsMatrix[0]:                                              #存入输入状态
        if enter!='\\' and enter!='&':
            EnterWorld.append(enter)
    for row in range(1,StatusNumber+1):                                             #NFA有穷状态集
        NFA_StatusWorld.append(NFA_StautsMatrix[row][0])
    DFA_Start = Empty_Closure(StartWorld)                                          #DFA开始状态
    for status in DFA_StatusWrold:
        for enter in EnterWorld:
            Empty_Closure(Enter_Closure(status,enter))

    DFA_StautsMatrix = [[] for _ in range(0, len(DFA_StatusWrold) + 1)]

    for row in range(0, len(DFA_StatusWrold) + 1):
        if row == 0:
            line = "\ a b c"
            line = line.split(' ')
            for column in range(len(line)):
                DFA_StautsMatrix[row].append(line[column])
        else:
            if row <=len(DFA_StatusWrold):
                number = DFA_StatusWrold[row-1]
                lineList=[]
                line = number
                for enter in EnterWorld:
                    if Empty_Closure(Enter_Closure(number,enter)) == False:
                        line = line+' '+'&'
                    else:
                        line = line + ' ' + Empty_Closure(Enter_Closure(number,enter))
                lineList = line.split(' ')
                for column in range(len(lineList)):
                    DFA_StautsMatrix[row].append(lineList[column])
    print("------------------------------DFA-------------------------------------")
    print("确定有穷自动机DFA_S:",end='')
    for number in DFA_StatusWrold:
        print(number,end='  ')
    print("\n确定有穷自动机DFA_∑:",end='')
    for number in EnterWorld:
        print(number,end='  ')
    print("\n确定有穷自动机DFA_S0:"+DFA_Start)
    for number in DFA_StatusWrold:
        if EndWorld in number:
            EndList.append(number)
    print("确定有穷自动机DFA_Z:",end='')
    for number in EndList:
        print(number,end='  ')
    print("\n确定有穷自动机DFA_δ:")
    for row in  DFA_StautsMatrix:
        print()
        for column in  row:
            print('%8s'%column,end='')


def Empty_Closure(string):
    global NFA_StautsMatrix, DFA_StautsMatrix, StartWorld, EndWorld,\
        StatusNumber, EnterNumber, EnterWorld, NFA_StatusWorld,DFA_StatusWrold
    List = []
    flag = 0
    NewList=[]
    NewStatus = string
    if string == False:
        return False
    if ',' not in string:
        while flag == 0 :
            if ',' not in string:
                row = NFA_StatusWorld.index(string) + 1
                if NFA_StautsMatrix[row][1]!='&' and NFA_StautsMatrix[row][1]!='*':
                    if NFA_StautsMatrix[row][1] not in NewStatus:
                        NewStatus = NewStatus+','+NFA_StautsMatrix[row][1]
                        string = NFA_StautsMatrix[row][1]
                    else:
                            flag = 1
                else:
                    flag = 1
            else:
                List = string.split(',')
                for number in range(len(List)):
                    if List[number] not in NewStatus:
                        NewStatus = NewStatus+','+List[number]
                        string = List[number]
                    elif List[number] in NewStatus and List[number] in NewStatus:
                        flag = 1
                        break
        if ',' in NewStatus:
            NewList = NewStatus.split(',')
            NewList=set(NewList)
            NewList=(sorted(set(NewList)))
            NewStatus=','.join(NewList)
        if NewStatus not in DFA_StatusWrold:
            DFA_StatusWrold.append(NewStatus)
        return NewStatus
    else:
        List = string.split(',')
        for number in List:
            row = NFA_StatusWorld.index(number) + 1
            if ',' not in NFA_StautsMatrix[row][1]:
                if NFA_StautsMatrix[row][1] != '&' and NFA_StautsMatrix[row][1] != '*':
                    if NFA_StautsMatrix[row][1] not in NewStatus:
                        NewStatus = NewStatus + ',' + NFA_StautsMatrix[row][1]
                    else:
                        pass
                else:
                    break
        if ',' in NewStatus:
            NewList = NewStatus.split(',')
            NewList=set(NewList)
            NewList=(sorted(set(NewList)))
            NewStatus=','.join(NewList)
        if NewStatus not in DFA_StatusWrold:
            DFA_StatusWrold.append(NewStatus)
        return NewStatus

def Enter_Closure(string,enter):
    global NFA_StautsMatrix, DFA_StautsMatrix, StartWorld, EndWorld, \
        StatusNumber, EnterNumber, EnterWorld, NFA_StatusWorld,DFA_StatusWrold
    status = '99999'
    List = []
    NewList = []
    if ',' not in string:
        row = NFA_StatusWorld.index(string)+1
        if NFA_StautsMatrix[row][EnterWorld.index(enter)+2]!='&'\
                and NFA_StautsMatrix[row][EnterWorld.index(enter)+2]!='*' \
                and string != NFA_StautsMatrix[row][EnterWorld.index(enter)+2]:

            if status == '99999':
                status =  NFA_StautsMatrix[row][EnterWorld.index(enter)+2]
            else:
                status = status + ',' + NFA_StautsMatrix[row][EnterWorld.index(enter)+2]
        elif  NFA_StautsMatrix[row][EnterWorld.index(enter)+2]!='&'\
                and NFA_StautsMatrix[row][EnterWorld.index(enter)+2]!='*' \
                and string == NFA_StautsMatrix[row][EnterWorld.index(enter)+2]:
            if string in status:
                pass
            else:
                if status == '99999':
                    status = NFA_StautsMatrix[row][EnterWorld.index(enter) + 2]
                else:
                    status = status + ',' + NFA_StautsMatrix[row][EnterWorld.index(enter) + 2]
        else:
           return False
        if status != '99999':
            if string not in status:
                if Enter_Closure(status,enter):
                    status = status+','+ Enter_Closure(status,enter)
            return status
        else:
            return False
    else:
        List = string.split(',')
        for number in List:
            row = NFA_StatusWorld.index(number) + 1
            if NFA_StautsMatrix[row][EnterWorld.index(enter)+2]!='&'\
                    and NFA_StautsMatrix[row][EnterWorld.index(enter)+2]!='*' \
                    and number != NFA_StautsMatrix[row][EnterWorld.index(enter)+2]:
                if status == '99999':
                    status =  NFA_StautsMatrix[row][EnterWorld.index(enter)+2]
                else:
                    status = status + ',' + NFA_StautsMatrix[row][EnterWorld.index(enter)+2]
            elif NFA_StautsMatrix[row][EnterWorld.index(enter)+2]!='&'\
                    and NFA_StautsMatrix[row][EnterWorld.index(enter)+2]!='*' \
                    and number == NFA_StautsMatrix[row][EnterWorld.index(enter)+2]:
                if number in status:
                    break
                else:
                    if status == '99999':
                        status = NFA_StautsMatrix[row][EnterWorld.index(enter) + 2]
                    else:
                        status = status + ',' + NFA_StautsMatrix[row][EnterWorld.index(enter) + 2]
            else:
                pass
        if status != '99999':
            NewList = status.split(',')
            for number in NewList:
                if number not in List:
                    if  Enter_Closure(number,enter):
                        status = status+','+ Enter_Closure(number,enter)
            return status
        else:
            return False

if __name__ == "__main__":
    main()

2.测试样例

输入开始状态:1
输入结束状态:3
输入状态个数:3
状态机输入个数:4
输入不确定有穷状态机转换表:
\ & a b c
1 1,3 & 2 3
2 & 1 3 1,2
3 & & & &

利用Python实现NFA到DFA的转化(子集法)_第1张图片

输入开始状态:1
输入结束状态:4
输入状态个数:4
状态机输入个数:4
输入不确定有穷状态机转换表:
\ & a b c
1 4 2,3 & &
2 & 2 4 &
3 & & & 3,4
4 & & & &

利用Python实现NFA到DFA的转化(子集法)_第2张图片

3.代码讲解

1.通过输入NFA开始状态,结束状态,输入状态个数,状态机权值个数(字母个数),还有映射关系,来确定NFA5元组,通过输入转换表,确定了映射关系,字母集,有穷状态集。

2.编写代码实现e-closure闭包即代码中Empty_Closure(string)。

3.编写代码实现I操作,即状态通过字母集中某一状态所能达到的所有状态,通过递归实现(导致代码比较长,如果输入超过6个状态,6个字母集会导致时间较长)。

4.将计算出来的结果保存至DFA 状态矩阵中。

ps:python中提供了方便的列表操作,写起来清晰流畅,不像C语言,数据结构比较难懂。将来若有时间,博主会发送C语言数据结构,邻接表版本。

你可能感兴趣的:(利用Python实现NFA到DFA的转化(子集法))