python怎么过滤出符合条件的_题目NFA转化DFA算法实现「建议收藏」

python怎么过滤出符合条件的_题目NFA转化DFA算法实现「建议收藏」DFA最小化原理所谓自动机的化简问题即是对任何一个确定有限自动机DFAM,构造另一个确定有限自动机DFAM’,有L(M)=L(M’),并且M’的状态个数不多于M的状态个数,而且可以肯定地说,能够找到一个状态个数为最小的

DFA最小化原理

所谓自动机的化简问题即是对任何一个确定有限自动机DFA M,构造另一个确定有限自动机DFA M’,有L(M)=L(M’),并且M’的状态个数不多于M的状态个数,而且可以肯定地说,能够找到一个状态个数为最小的M’。

下面首先来介绍一些相关的基本概念。

设Si是自动机M的一个状态,从Si出发能导出的所有符号串集合记为L(Si)。

设有两个状态Si和Sj,若有L(Si)=L(Sj),则称Si和Sj是等价状态。

上图所示的自动机中L(B)=L(C)={1},所有状态B和状态C是等价状态。

又例如终态导出的符号串集合中必然包含空串ε,而非终止状态导出的符号串集合中不可能包含空串ε,所以终态和非终止状态是不等价的。

对于等价的概念,我们还可以从另一个角度来给出定义。

给定一个DFA M,如果从某个状态P开始,以字符串w作为输入,DFA M将结束于终态,而从另一状态Q开始,以字符串w作为输入,DFA M将结束于非终止状态,则称字符串w把状态P和状态Q区分开来。

把不可区分开来的两个状态称为等价状态。

设Si是自动机M的一个状态,如果从开始状态不可能达到该状态Si,则称Si为无用状态。

设Si是自动机M的一个状态,如果对任何输入符号a都转到其本身,而不可能达到终止状态,则称Si为死状态。

化简DFA关键在于把它的状态集分成一些两两互不相交的子集,使得任何两个不相交的子集间的状态都是可区分的,而同一个子集中的任何两个状态都是等价的,这样可以以一个状态作为代表而删去其他等价的状态,然后将无关状态删去,也就获得了状态数最小的DFA。

下面具体介绍DFA的化简算法:

首先将DFA M的状态划分出终止状态集K1和非终止状态集K2。

K=K1∪K2

由上述定义知,K1和K2是不等价的。

对各状态集每次按下面的方法进一步划分,直到不再产生新的划分。

设第i次划分已将状态集划分为k组,即:

K=K1(i)∪K2(i)∪…∪Kk(i)

对于状态集Kj(i)(j=1,2,…,k)中的各个状态逐个检查,设有两个状态Kj’、 Kj’’∈Kj(i),且对于输入符号a,有:

F(Kj‘,a)=Km

F(Kj”,a)=Kn

如果Km和Kn属于同一个状态集合,则将Kj’和Kj’’放到同一集合中,否则将Kj’和Kj’’分为两个集合。

重复第(2)步,直到每一个集合不能再划分为止,此时每个状态集合中的状态均是等价的。

合并等价状态,即在等价状态集中取任意一个状态作为代表,删去其他一切等价状态。

若有无关状态,则将其删去。

根据以上方法就将确定有限自动机进行了简化,而且简化后的自动机是原自动机的状态最少的自动机。

Hopcroft算法原理

算法抽象:

1: Q/θ ← {F, Q − F}

2: while (∃U, V ∈ Q/θ, a ∈ Σ) s.t. Equation 1 holds do

3: Q/θ ← (Q/θ − {U}) ∪ {U ∩ δ^-1(V, a), U − U ∩ δ^-1(V, a)}

4: end while

算法细化:

1:W ← {F, Q − F}    # 有些版本上只是 W ← {F }

2: P ← {F, Q − F}

3: while W is not empty do

4:     select and remove S from W

5:     for all a ∈ Σ do

6:         la ← δ^-1(S, a)

7:         for all R in P such that R ∩ la ≠ ∅ and R ∉ la do

8:             partition R into R1 and R2: R1 ← R ∩ la and R2 ← R − R1

9:             replace R in P with R1 and R2

10:           if R ∈ W then

11:               replace R in W with R1 and R2

12:           else

13:                 if |R1| ≤ |R2| then

14:                     add R1 to W

15:                 else

16:                     add R2 to W

17:                 end if

18:             end if

19:         end for

20:    end for

21: end while

流程图

python怎么过滤出符合条件的_题目NFA转化DFA算法实现「建议收藏」

Python代码

Python

from graphviz import Digraph

import random

from copy import deepcopy

class Part:

def __init__(self, src, edge, dst):

self.src = src

self.edge = edge

self.dst = dst

def move(DFA, src, edge):

for i in range(len(DFA)):

if DFA[i].src[0] == src and DFA[i].edge == edge:

return DFA[i].dst[0]

return ”

def get_source_set(target_set, char, DFA):

global allstatus

allstatusSet = set(allstatus)

source_set = set()

for state in allstatusSet:

try:

if move(DFA, state, char) in target_set:

source_set.update(state)

except KeyError:

pass

return source_set

def hopcroft_algorithm(DFA):

global sigma

global endSet

global allstatus

cins = set(sigma)

termination_states = set(endSet)

total_states = set(allstatus)

not_termination_states = total_states – termination_states

P = [termination_states, not_termination_states]

W = [termination_states, not_termination_states]

while W:

A = random.choice(W)

W.remove(A)

for char in cins:

X = get_source_set(A, char,DFA)

P_temp = []

for Y in P:

S = X & Y

S1 = Y – X

if len(S) and len(S1):

P_temp.append(S)

P_temp.append(S1)

if Y in W:

W.remove(Y)

W.append(S)

W.append(S1)

else:

if len(S) <= len(S1):

W.append(S)

else:

W.append(S1)

else:

P_temp.append(Y)

P = deepcopy(P_temp)

return P

def indexMinList(minList, a):

for i in range(len(minList)):

if a in minList[i]:

return i

return ”

DFA = []

DFA2 = []

DFADic = {}

sigma = [‘a’, ‘b’]

# dot = Digraph(comment=’The Test Table’)

dot = Digraph(“DFA”)

num = int(input(‘input:’))

for i in range(num):

x = input()

y = input()

z = input()

temp = []

temp.append(x)

temp.append(y)

DFA2.append(temp)

DFADic[tuple(temp)] = y

temp = Part(x, y, z)

DFA.append(temp)

if i == 1:

dot.node(name=x, color=’blue’)

dot.edge(x, z, y)

else:

dot.node(name=x, color=’black’)

dot.edge(x, z, y)

for i in range(len(DFA)):

print(DFA[i].src, DFA[i].edge, DFA[i].dst)

endSet = []

endNum = int(input(‘input end num:’))

for i in range(endNum):

temp = input()

endSet.append(temp)

startSet = []

allSet = []

for i in range(len(DFA)):

if DFA[i].src[0] not in endSet:

startSet.append(DFA[i].src[0])

if DFA[i].dst[0] not in endSet:

startSet.append(DFA[i].src[0])

allstatus = startSet

allstatus.extend(endSet)

dot.render(‘DFA.gv’, view=True)

minList = hopcroft_algorithm(DFA)

minDFA = []

print(minList)

for i in range(len(minList)):

dstList = [0, 0] # 用来存储每种状态经过a和b变换后的结果

for j in range(len(minList[i])):

listi = list(minList[i])

if dstList[0] == 0 and move(DFA, listi[j], sigma[0]) != ” and indexMinList(minList, move(DFA, listi[j], sigma[0])) != ”:

print(indexMinList(minList, move(DFA, listi[j], sigma[0])))

dstList[0] = min(minList[indexMinList(minList, move(DFA, listi[j], sigma[0]))])

# 使用Min函数的原因是为了重新给每种状态命名,选去每个状态中的最小的即可

if dstList[1] == 0 and move(DFA,listi[j], sigma[1]) != ”and indexMinList(minList, move(DFA, listi[j], sigma[1])) != ”:

dstList[1] = min(minList[indexMinList(minList, move(DFA, listi[j], sigma[1]))])

if dstList[0] != 0:

temp = Part(min(minList[i]),’a’,dstList[0])

minDFA.append(temp)

if dstList[1] != 0:

temp2 = Part(min(minList[i]), ‘b’, dstList[1])

minDFA.append(temp2)

dot2 = Digraph(‘测试图片’)

for i in range(len(minDFA)):

print(minDFA[i].src, minDFA[i].edge,minDFA[i].dst)

if i == 1:

dot2.node(name = minDFA[i].src, color=’red’)

dot2.edge(minDFA[i].src, minDFA[i].dst, minDFA[i].edge)

else:

dot2.node(name=minDFA[i].src, color=’black’)

dot2.edge(minDFA[i].src, minDFA[i].dst, minDFA[i].edge)

dot2.render(‘minDFA.gv’, view=True)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

fromgraphvizimportDigraph

importrandom

fromcopyimportdeepcopy

classPart:

def__init__(self,src,edge,dst):

self.src=src

self.edge=edge

self.dst=dst

defmove(DFA,src,edge):

foriinrange(len(DFA)):

ifDFA[i].src[0]==srcandDFA[i].edge==edge:

returnDFA[i].dst[0]

return”

defget_source_set(target_set,char,DFA):

globalallstatus

allstatusSet=set(allstatus)

source_set=set()

forstateinallstatusSet:

try:

ifmove(DFA,state,char)intarget_set:

source_set.update(state)

exceptKeyError:

pass

returnsource_set

defhopcroft_algorithm(DFA):

globalsigma

globalendSet

globalallstatus

cins=set(sigma)

termination_states=set(endSet)

total_states=set(allstatus)

not_termination_states=total_states-termination_states

P=[termination_states,not_termination_states]

W=[termination_states,not_termination_states]

whileW:

A=random.choice(W)

W.remove(A)

forcharincins:

X=get_source_set(A,char,DFA)

P_temp=[]

forYinP:

S=X&Y

S1=Y-X

iflen(S)andlen(S1):

P_temp.append(S)

P_temp.append(S1)

ifYinW:

W.remove(Y)

W.append(S)

W.append(S1)

else:

iflen(S)<=len(S1):

W.append(S)

else:

W.append(S1)

else:

P_temp.append(Y)

P=deepcopy(P_temp)

returnP

defindexMinList(minList,a):

foriinrange(len(minList)):

ifainminList[i]:

returni

return”

DFA=[]

DFA2=[]

DFADic={}

sigma=[‘a’,’b’]

# dot = Digraph(comment=’The Test Table’)

dot=Digraph(“DFA”)

num=int(input(‘input:’))

foriinrange(num):

x=input()

y=input()

z=input()

temp=[]

temp.append(x)

temp.append(y)

DFA2.append(temp)

DFADic[tuple(temp)]=y

temp=Part(x,y,z)

DFA.append(temp)

ifi==1:

dot.node(name=x,color=’blue’)

dot.edge(x,z,y)

else:

dot.node(name=x,color=’black’)

dot.edge(x,z,y)

foriinrange(len(DFA)):

print(DFA[i].src,DFA[i].edge,DFA[i].dst)

endSet=[]

endNum=int(input(‘input end num:’))

foriinrange(endNum):

temp=input()

endSet.append(temp)

startSet=[]

allSet=[]

foriinrange(len(DFA)):

ifDFA[i].src[0]notinendSet:

startSet.append(DFA[i].src[0])

ifDFA[i].dst[0]notinendSet:

startSet.append(DFA[i].src[0])

allstatus=startSet

allstatus.extend(endSet)

dot.render(‘DFA.gv’,view=True)

minList=hopcroft_algorithm(DFA)

minDFA=[]

print(minList)

foriinrange(len(minList)):

dstList=[0,0]# 用来存储每种状态经过a和b变换后的结果

forjinrange(len(minList[i])):

listi=list(minList[i])

ifdstList[0]==0andmove(DFA,listi[j],sigma[0])!=”andindexMinList(minList,move(DFA,listi[j],sigma[0]))!=”:

print(indexMinList(minList,move(DFA,listi[j],sigma[0])))

dstList[0]=min(minList[indexMinList(minList,move(DFA,listi[j],sigma[0]))])

# 使用Min函数的原因是为了重新给每种状态命名,选去每个状态中的最小的即可

ifdstList[1]==0andmove(DFA,listi[j],sigma[1])!=”andindexMinList(minList,move(DFA,listi[j],sigma[1]))!=”:

dstList[1]=min(minList[indexMinList(minList,move(DFA,listi[j],sigma[1]))])

ifdstList[0]!=0:

temp=Part(min(minList[i]),’a’,dstList[0])

minDFA.append(temp)

ifdstList[1]!=0:

temp2=Part(min(minList[i]),’b’,dstList[1])

minDFA.append(temp2)

dot2=Digraph(‘测试图片’)

foriinrange(len(minDFA)):

print(minDFA[i].src,minDFA[i].edge,minDFA[i].dst)

ifi==1:

dot2.node(name=minDFA[i].src,color=’red’)

dot2.edge(minDFA[i].src,minDFA[i].dst,minDFA[i].edge)

else:

dot2.node(name=minDFA[i].src,color=’black’)

dot2.edge(minDFA[i].src,minDFA[i].dst,minDFA[i].edge)

dot2.render(‘minDFA.gv’,view=True)

测试

测试数据:

起始节点、边、终止节点的表示

共有14个边,7个节点

python怎么过滤出符合条件的_题目NFA转化DFA算法实现「建议收藏」

图形显示:

python怎么过滤出符合条件的_题目NFA转化DFA算法实现「建议收藏」

刚开始的子集为[{C,D,E,F},{S,A,B}]

实验结束后的结果:

python怎么过滤出符合条件的_题目NFA转化DFA算法实现「建议收藏」

最简化的DFA为:

C为终止节点,S为起始节点

python怎么过滤出符合条件的_题目NFA转化DFA算法实现「建议收藏」

难点与解决的方法

在DFA最小化的过程中受限要去除无用状态,再使用子集分割算法处理。根据资料查找到一个快速的DFA最小化算法,叫做Hopcroft算法,通过该算法,能够处理不同大小字母表的DFA。

在进行子集分割算法后,要合并等价的节点并且重命名使用graphviz输出,在这一步,合并并重命名节点需要注意所有重复节点的入度和出度均要考虑,只有这样才能避免新的最小化的DFA的边不遗漏。

今天的文章python怎么过滤出符合条件的_题目NFA转化DFA算法实现「建议收藏」分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/87853.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注