6.1. Khái niệm về Pushdown Automata (PDA)
Lớp RL được sinh ra từ RG và được đoán nhận bởi FA; CFL được sinh ra từ CFG.
Câu hỏi: Liệu có thể được đốn nhận CFL bởi một FA? Nếu có thì automata đó như thế nào?
Ví dụ 6.1: Automata đốn nhận ngơn ngữ dạng: {0n1n}; S → 0S1 | ε Ví dụ 6.2: Automata đốn nhận ngơn ngữ dạng: {wcwR | w ∈ (0+1)*}; S → 0S0 | 1S1 | c Ví dụ 6.3: Automata đốn nhận ngơn ngữ dạng: {wwR | w ∈ (0+1)*}; S → 0S0 | 1S1 | ε Ví dụ 6.4: {a2nbn}; S → aaSb | ε
Ví dụ 6.5: về kiểm tra cân bằng của chuỗi đóng mở ngoặc sử dụng stack:
while (input symbol is “[”) { <push “[” onto the stack>;
while (input symbol is “]”) && (top of stack is “[”)<pop>; }
if (all of input read) && (top of stack is “ ”) <accept>.
Xét chuỗi nhập vào “[ [ ] [ ] ]”.
6.1.1. PDA và các khái niệm liên quan
PDA là một FA với sự bổ sung thêm một ngăn xếp (stack) đóng vai trị
bộ nhớ, do vậy khả năng ghi nhớ của FA được tăng lên, dẫn đến PDA có khả năng đốn nhận lớp ngôn ngữ rộng hơn là RL (RG, RE);
Stack hoạt động theo nguyên lý FILO (LIFO), do đó FA sử dụng bộ nhớ
có tên gọi là Pushdown automata;
Tại mỗi thời điểm, PDA điều khiển đồng thời cả dòng dữ liệu nhập vào (băng nhập- tape) và bộ nhớ - bộ đẩy xuống (stack). Khi đọc một tín hiệu vào, PDA có thể chuyển sang một trạng thái mới, hoặc thêm, xóa đi dữ liệu từ stack, hoặc đồng thời cả hai;
Lớp PDA có khả năng đốn nhận lớp CFL, trong đó bao gồm các ngơn
ngữ lập trình hiện đại;
Có 2 dạng chuyển trạng thái (transitions):
Dạng 1: phụ thuộc vào ký hiệu nhập. Tại mỗi trạng thái, với 1 ký hiệu đọc
vào và đỉnh stack, PDA sẽ lựa chọn trạng thái kế tiếp và một chuỗi ký hiệu thay thế trên stack, đầu đọc dịch sang phải 1 ký hiệu;
Dạng 2: không phụ thuộc vào ký hiệu nhập (dịch chuyển ε). Đầu đọc đứng
im. Ngăn xếp biến đổi.
Có 2 cách định nghĩa ngơn ngữ chấp nhận bởi PDA:
Ngôn ngữ chấp nhận bởi stack rỗng: Gồm các chuỗi nhập mà sau bước
Ngôn ngữ chấp nhận bởi trạng thái kết thúc: Gồm các chuỗi nhập mà sau bước chuyển cuối cùng rơi vào một trong các trạng thái kết thúc;
ĐN 6.1: một PDA A là một hệ thống 7 thành phần A (Q, Σ, Γ, δ, q0, Z0, F)
Q : tập hữu hạn các trạng thái;
Σ : bộ chữ cái nhập (input alphabet); Γ : bộ chữ cái stack (stack alphabet);
δ : hàm chuyển Q x (Σ È {ε}) x Γ → tập con của Q x Γ*; q0 : trạng thái khởi đầu;
Z0 : ký hiệu bắt đầu trên stack;
F Q : tập các trạng thái kết thúc (nếu PDA chấp nhận chuỗi bằng Stack rỗng thì F = Ø).
ĐN 6.2: Hàm chuyển δ phụ thuộc ký hiệu nhập:
δ(q, a, z) = { (p1, γ1), (p2, γ2), ..., (pm, γm) }, trong đó: trạng thái hiện thời là q;
ký tự đọc hiện thời là a;
ký hiệu trên đỉnh hiện thời của stack là z; trạng thái chuyển tới là pi , 1 i m; Thay thế z bằng γi trên đỉnh stack;
Chuyển đầu đọc tới vị trí ký tự tiếp theo trên băng. ĐN 6.3: Hàm chuyển δ không phụ thuộc ký hiệu nhập:
δ(q, ε, z) = { (p1, γ1), (p2, γ2), ..., (pm, γm) },
ĐN 6.4: Hình thái (configuration or ID) của PDA dùng để ghi nhớ trạng
thái và nội dung của stack:
(q, aw, zα) →(p, w, βα) nếu δ(q, a, z) chứa (p, β) ĐN 6.5: Ngôn ngữ chấp nhận bởi PDA:
Ngôn ngữ được chấp nhận bằng trạng thái kết thúc:
L (A) = {w | (q0, w, Z0) →* (p, ε, γ) với p F và γ Γ*} Ngôn ngữ được chấp nhận bởi stack rỗng:
N (A) = {w | (q0, w, Z0) →* (p, ε, ε) với p Q} q p 1 p 2 p m
6.1.2. PDA khơng đơn định (NPDA)
Ví dụ 6.7: thiết kế PDA chấp nhận ngôn ngữ trong vd 6.3:
{wwR | w (0 + 1)*} bằng Stack rỗng
Nhận xét: do khơng có ký hiệu c để biết thời điểm chuyển từ trạng thái q1 sang q2, → bắt buộc phải đoán thử khi thấy 2 ký hiệu liên tiếp giống nhau.
Nếu ký hiệu thuộc chuỗi xuôi: giữ nguyên trạng thái q1 và push vào stack; Nếu ký hiệu thuộc chuỗi ngược: chuyển sang trạng thái q2 và pop khỏi Stack.
6.1.3. PDA đơn định (DPDA)
ĐN 6.6: Một PDA A(Q, Σ, Γ, δ, q0, Z0, F) được gọi là đơn định nếu: "q Q và Z Γ: nếu δ(q, ε, Z) ≠ Ø thì δ(q, a, Z) = Ø,a Σ
Khơng có q Q, Z Γ và a (Σ {ε}) mà δ(q, a, Z) chứa nhiều hơn một phần tử.
Chú ý: đối với PDA thì dạng đơn định và khơng đơn định là khơng tương đương nhau.
Ví dụ 6.7: wwR được chấp nhận bởi PDA không đơn định, nhưng không được chấp nhận bởi bất kỳ một PDA đơn định nào.
6.2. Sự tương đương giữa 2 dạng PDA
6.2.1. Biến đổi tương đương từ dạng 2 sang dạng 1
Định lý 6.1: Nếu một CFL L được chấp nhận bởi một PDA chấp nhận
chuỗi bởi trạng thái kết thúc A2 thì L cũng được chấp nhận bởi một PDA chấp nhận chuỗi bởi Stack rỗng A1
Giải thuật:
Đặt A2 = (Q, Σ, Γ, δ, q0, Z0, F) và
A1 = (Q {qe, q0'}, Σ, Γ, δ', q0', X0, Ø) 1. δ'(q0', ε, X0) = {(q0, Z0X0)}
2. δ'(q, a, Z) chứa mọi phần tử của δ(q, a, Z) , a (Σ {ε}) 3. δ'(q, ε, Z) chứa (qe, ε) với "q F và Z (Γ {X0}) 4. δ'(qe, ε, Z) chứa (qe, ε) với "Z (Γ {X0})
6.2.2. Biến đổi tương đương từ dạng 1 sang dạng 2
Định lý 6.2: Nếu một CFL L được chấp nhận bởi một PDA chấp nhận
chuỗi bởi stack rỗng thì L cũng được chấp nhận bởi một PDA chấp nhận chuỗi bởi trạng thái kết thúc.
Đặt: A1 = (Q, Σ, Γ, δ, q0, Z0, F)
A2 = (Q È {q0', qf}, Σ, Γ {X0}, δ', q0', X0, {qf}) 1. δ'(q0', ε, X0) = {(q0, Z0X0)}
2. δ'(q, a, Z) = δ(q, a, Z) với a (Σ {ε}) 3. δ'(q, ε, X0) chứa (qf, ε) với q Q
6.3. Sự tương đương giữa PDA và CFG
6.3.1. Biến đổi tương đương từ CFG sang PDA
Định lý 6.3: Nếu L là một ngôn ngữ phi ngữ cảnh thì tồn tại PDA chấp
nhận chuỗi với stack rỗng A sao cho L = N(A).
1. Xây dựng văn phạm G = < Σ, Δ, S, P > thỏa dạng chuẩn Greibach và L(G) không chứa ε
2. Đặt A = ({q}, Σ, Γ, δ, q, S, Ø) là PDA chấp nhận L với Stack rỗng δ'(q, a, A) = (q, γ) khi và chỉ khi A → aγ
Ví dụ 6.8: S → aAA ; A → aS | bS | a NPDA tương đương
A = ({q}, {a, b}, {S, A}, δ, q, S, Ø) với hàm chuyển δ như sau:
δ(q, a, S) = {(q, AA)} δ(q, a, A) = {(q, S), (q, ε)} δ(q, b, A) = {(q, S)}
6.3.2. Biến đổi tương đương từ PDA sang CFG
Định lý 6.4: Nếu L được chấp nhận bởi một PDA chấp nhận chuỗi bởi
stack rỗng thì L là CFL.
Giải thuật: Đặt PDA A = (Q, Σ, Γ, δ, q0, Z0, Ø) chấp nhận L với stack rỗng. Đặt G = < Σ, Δ, S, P > là CFG, trong đó:
1. Δ là tập các đối tượng dạng [q, A, p]. 2. Thêm vào ký hiệu bắt đầu S
3. P là tập các luật sinh dạng: S → [q0, Z0, q] với "q Ỵ Q
[q, A, qm+1] → a [q1, B1, q2][q2, B2, q3]...[qm, Bm, qm+1] δ(q, a, A) có chứa (qm+1, B1B2...Bm)
Nếu m = 0 thì luật sinh có dạng [q, A, q1] → a