编译原理实验——将NFA转化为DFA

转自http://blog.csdn.net/lingyu940/article/details/5070137


将NFA转化为DFA


1.实验目的


输入: 非确定有限(穷)状态自动机。

输出: 确定化的有限(穷)状态自动机

2.实验原理

采用子集对NFA转DFA。

(1) 若NFA的全部初态为S1,S2,…,Sn,则令DFA的初态为:

S=[S1,S2,…,Sn],

其中方括号用来表示若干个状态构成的某一状态。

(2) 设DFA的状态集K中有一状态为[Si,Si+1,…,Sj],若对某符号a∈∑,在NFA中有F({ Si,Si+1,…,Sj },a)={ Si’,Si+1’,…,Sk’ }

则令F({ Si,Si+1,…,Sj },a)={ Si’,Si+1’,…,Sk’ }为DFA的一个转换函数。若[ Si’,Si+1’,…,Sk‘ ]不在K中,则将其作为新的状态加入到K中。

(3) 重复第2步,直到K中不再有新的状态加入为止。

(4) 上面得到的所有状态构成DFA的状态集K,转换函数构成DFA的F,DFA的字母表仍然是NFA的字母表∑。

(5) DFA中凡是含有NFA终态的状态都是DFA的终态。

还可以采用另一种操作性更强的描述方式。首先给出两个相关定义。

假设I是NFA M状态集K的一个子集(即I∈K),则定义ε-closure(I)为:

(1) 若Q∈I,则Q∈ε-closure(I);

(2) 若Q∈I,则从Q出发经过任意条ε弧而能到达的任何状态Q’,则Q’∈ε-closure(I)。

状态集ε-closure(I)称为状态I的ε闭包。

假设NFA M=(K,∑,F,S,Z),若I∈K,a∈∑,则定义Ia=ε-closure(J),其中J是所有从ε-closure(I)出发,经过一条a弧而到达的状态集。

NFA确定化的实质是以原有状态集上的子集作为DFA上的一个状态,将原状态间的转换为该子集间的转换,从而把不确定有限自动机确定化。经过确定化后,状态数可能增加,而且可能出现一些等价状态,这时就需要简化

3.实验内容

⑴ 实现计算闭包closure(I)的算法;

⑵ 实现转换函数move(q,a)的算法;

⑶ 输出NFA转DFA的结果。



DFA和NFA存储使用的数据结构为图中的邻接链表。

typedef struct ArcNode{

int adjvex; //该弧所指向的顶点的位置

char info; //权

struct ArcNode *nextarc; //指向下一条弧的指针

}ArcNode;

typedef struct VNode{

char data; //顶点信息

ArcNode *firstarc; //指向第一条依附该顶点的弧的指针

}VNode;

每个链表的第一个数据单元为N(D)FA的状态,后边的结点存储内容有指向的边和边上的权值。

例如课本图4.3的NFA M表示如下:




4.实验心得

1.一般来说,我们接触到的N(D)FA图的边数比较少,所以在选取数据结构存储时,选择邻接链表,相对于使用二维或三维数组,存储效率得到了提高。

2.在求e_closure集合时,因为是任意个空转移,因此使用深度遍历的方法,先求出一个状态的e_closure集,再用循环求出状态集的e_closure集
以下是 Python 代码实现 NFA DFA 的过程,包含输入输出: ```python def epsilon_closure(states, transitions): """ 计算状态集合 states 的 epsilon 闭包 """ closure = set(states) stack = list(states) while stack: state = stack.pop() if state in transitions and '' in transitions[state]: for s in transitions[state]['']: if s not in closure: closure.add(s) stack.append(s) return closure def move(states, transitions, symbol): """ 计算状态集合 states 在符号 symbol 下的移状态 """ move_states = set() for state in states: if state in transitions and symbol in transitions[state]: move_states.update(transitions[state][symbol]) return move_states def nfa_to_dfa(nfa_states, nfa_transitions, start_state): """ 将 NFA 换为 DFA """ dfa_states = [] dfa_transitions = {} dfa_start_state = frozenset(epsilon_closure([start_state], nfa_transitions)) unmarked_states = [dfa_start_state] while unmarked_states: dfa_state = unmarked_states.pop() if dfa_state not in dfa_states: dfa_states.append(dfa_state) for symbol in nfa_alphabet: move_states = move(dfa_state, nfa_transitions, symbol) closure = epsilon_closure(move_states, nfa_transitions) if closure: dfa_transitions[(dfa_state, symbol)] = frozenset(closure) if closure not in dfa_states + unmarked_states: unmarked_states.append(closure) return dfa_states, dfa_transitions, dfa_start_state # 输入示例 nfa_states = {'q0', 'q1', 'q2', 'q3'} nfa_alphabet = {'0', '1'} nfa_transitions = { 'q0': {'': {'q1', 'q2'}}, 'q1': {'0': {'q1'}, '1': {'q1', 'q3'}}, 'q2': {'0': {'q2', 'q3'}, '1': {'q2'}}, 'q3': {'1': {'q3'}} } start_state = 'q0' # 输出示例 dfa_states, dfa_transitions, dfa_start_state = nfa_to_dfa(nfa_states, nfa_transitions, start_state) print('DFA States:', dfa_states) print('DFA Transitions:', dfa_transitions) print('DFA Start State:', dfa_start_state) ``` 在上述代码中,我们首先定义了输入的 NFA 状态集合 `nfa_states`、字母表 `nfa_alphabet`、移函数 `nfa_transitions` 和起始状态 `start_state`。接着调用 `nfa_to_dfa()` 函数将 NFA 换为 DFA,并输出换后的 DFA 状态集合、移函数和起始状态。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值