Đặt vấn đềMục đích của bài toán: Từ 1 NPDA cho trước viết chương trình biến đổi NPDA đó về văn phạm phi ngữ cảnh CFG sao cho CFG đó sinh ra ngôn ngữ được chấp nhận bởi NPDA đã cho.. Cơ
Trang 1Contents
I Đặt vấn đề 1
II Cơ sở lý thuyết 1
III Cấu trúc chương trình 4
3.1 Cấu trúc chương trình 4
3.2 Sơ đồ khối các bước giải quyết công việc 5
IV Giao diện chính của chương trình 6
V Phụ lục 7
VI Tài liệu tham khảo 16
Trang 2I Đặt vấn đề
Mục đích của bài toán:
Từ 1 NPDA cho trước viết chương trình biến đổi NPDA đó về văn phạm phi ngữ cảnh( CFG) sao cho CFG đó sinh ra ngôn ngữ được chấp nhận bởi NPDA đã cho.
Các vấn đề mà đề tài cần giải quyết:
- Từ 1 NPDA cho trước ta đưa về 1 NPDA tương đương chỉ có 1 trạng thái kết
- Đưa tất cả các hàm chuyển về dạng:
(qi ,a, A) (qj, BC)
- Sau đó chuyển NPDA về văn phạm phi ngữ cảnh (CFG).
II Cơ sở lý thuyết
Bổ đề 1 : Với mọi NPDA luôn có một NPDA tương ứng thỏa mãn hai điều kiệu
sau:
1.Chỉ có 1 trạng thái kết thúc và NPDA kết thúc khi stack rỗng.
2.Mọi chuyển trạng thái đều có dạng:
(qi ,a, A)={cc1, c2, , cn}
trong đó:
ci = (qj , ) (7.5) hoặc:
ci = (qj, BC) (7.6) tức là 1 di chuyển hoặc tăng hoặc giảm stack 1 ký hiệu đơn.
Bây giờ ta sẽ đi vào chứng minh bổ đề 1 bằng cách xây dựng một NPDA tương
Trang 3-Điều kiện 1:
Giả sử một NPDA có nhiều hơn một trạng thái kết thúc qi, qj, qk Ta chuyển hết tất cả các trạng thái kết thúc qj, qk về trạng thái kết thúc qi khi stack rỗng Điều
này tương đương với việc thêm các chuyển dịch lamda như sau vào (qqj, , z) ->) -> (q qi, z) ->), (q qk, , z) ->) -> (qqi, z) ->), với qi là trạng thái kết thúc đầu tiên và qj, qk là các trạng thái kết thúc còn lại Sau đó ta gán lại cho qj, qk thành các trạng thái không kết thúc Điều kiện 1 đã thỏa.
-Điều kiện 2:
* Đối với các chuyển dịch có dạng:
(qqi, a, A) -> (q) -> (qqj, B)) tức là thay A trên đỉnh Stack thành B (số phần tử trong stack
không đổi) ta tạo một trạng thái mới qt Sau đó ta sẽ dùng trạng thái qt này để làm bước trung gian chuyển từ trạng thái qi sang qj và thay thế A trên đỉnh Stack thành
B
Bước làm như sau:
Xóa chuyển trạng thái (qqi, a, A) -> (q) -> (qqj, B)) đi và thay nó bằng 2 chuyển trạng thái:
(q qi, a, A) -> (q)->(qqt, B)B)) //Thay ký tự A trên đỉnh Stack thành 2 ký tự B và chuyển sang qt.
(qqt, , B))->(qqj, ) //Từ qt, không cần nhận ký tự nào từ ngõ nhập và đỉnh Stack lúc này là B Ta bỏ đi 1 ký tự B.
Như thế, 2 bước chuyển trạng thái này tương đương với bước chuyển trạng thái
(qqi, a, A) -> (q)->(qqj, B)).
*Đối với các chuyển dịch có dạng:
(qqi, a, A) -> (q) -> (qqj, B)CDE) ) tức là thay thế A trên đỉnh Stack thành BCDE ( số phần
tử trên đỉnh Stack tăng thêm nhiều hơn 1) ta cũng tạo một trạng thái qt trung gian mới Sau đó dùng trạng thái qt này để làm bước trung gian để thay thế A bằng chuỗi BCDEF Các bước thực hiện lần lược như sau:
(q qi, a, A) -> (q) -> (qqt, DE) ) //Chuyển sang trạng thái tạm qt và thay A bằng
DE Đỉnh stack lúc này là DE.
Trang 4(qqt, , D) -> (qqt, CD) //Thay D bằng CD mà không cần đọc ký tự nào vào Đỉnh stack lúc này là CDE Trạng thái vẫn ở qt.
(qqt, , C) -> (qqj, B)C) //Thay C bằng BC và chuyển xuống trạng thái qj
như yêu cầu Đỉnh stack lúc này là BCDE.
- Như thế với 3 bước trung gian ta đã thực hiện được (qqi, a, A) -> (q) -> (qqj, B)CDE) )
thỏa mãn điều kiện.
- Sau khi đã chuyển về NPDA thỏa mãn bổ đề ta sẽ chuyển NPDA này thành văn phạm.
- Với các chuyển dịch (7.5) ta sẽ sinh ra luật sinh tương ứng:
(qqi A) -> (q qj ) -> a
- Còn với các chuyển dịch có dạng (7.6) thì sẽ có tập luật sinh:
(qqi A) -> (q qj) -> a(qqj B) ql)(qql C qk)
trong đó ql và qk là những trạng thái có thể lấy được trong tập Q = {cq0, ,qn}.
- Cuối cùng ta lấy (qq0 z) -> qf) là biến bắt đầu của văn phạm với qf là biến kết thúc đơn của NPDA.
*Bước cuối cùng của thao tác này là loại bỏ những luật sinh vô dụng Các bước như sau:
B)1: Đầu tiên ta tạo một tập biến hữu dụng (BHD) là những biến (qqi A) -> (q qj) có dạng: (qqi A) -> (q qj) -> a.
B)2: Đối với những luật sinh (qqi A) -> (q qj) -> a(qqj B) ql) (qql C qk) với (qqi A) -> (q qj) là biến không thuộc tập BHD nhưng (qqj B) ql), (qql C qk) thuộc BHD thì thêm (qqi A) -> (q qj) vào B)3: Lặp bước 2 cho đến khi không thể thêm phần tử nào vào được.
B)4: Đối với mỗi luật sinh (qqi A) -> (q qj) -> a(qqj B) ql) (qql C qk) mà (qqi A) -> (q qj) hoặc (qj B)
ql) hoặc (qql C qk) không thuộc tập BHD thì bỏ loại bỏ luật sinh đó (thực ra chỉ cần xét (qqi A) -> (q qj) có thuộc tập BHD không thôi vì nếu (qqj B) ql) và (qql C qk) đều thuộc BHD thì (qqi A) -> (q qj) cũng thuộc tập này).
Như thế ta được Văn phạm G tương đương với NPDA M đã cho.
Trang 5III Cấu trúc chương trình
III.1 Cấu trúc chương trình
- Lớp NPDA) -> (q bao gồm các thành phần cơ bản của 1 NPDA (q_max, xichma,
gama, delta, qst, z, F) trong đó: q_max là số trạng thái lón nhất của NPDA, xichma là tập ký tự kết thúc, gama là tập ký tự của stack, delta là các hàm chuyển, qst là trạng thía bắt đầu, z là ký tự khởi đầu stack, F là mảng bool xác định 1 trạng thái thuộc NPDA có là trạng thái kết thúc hay không Trong lớp ta xây dựng các phương thức đưa 1 NPDA bất kỳ về 1 NPDA tương đương thỏa
mãn điều kiện (1), (2) cụ thể là các phương thức thoadieukien1(q), thoadieukien2(q), 1 phương thức chuyển NPDA thành văn phạm phi ngữ cảnh (CFG) cụ thể là phương thức toVP(q).
- Lớp VP bao gồm các thành phần cơ bản của 1 CFG (T,V, S, P) trong đó T là
tập cá ký tự kết thúc, V là tập các ký tự chưa kết thúc, S là ký tự bắt đầu, P là
tập các luật sinh Trong lớp ta xây dựng các phương thức sau: setT(q) để cài đặt tập ký tự kết thúc, addV(q) để thêm vào các ký tự chưa kết thúc, addP(q) để thêm các luật sinh cho văn phạm, loaiboluatsinhvodung(q) để loại bỏ các luật
sinh vô dụng trong CFG.
- Lớp luatsinh để tạo 1 đối tượng luật sinh cho văn phạm, gồm có vetrai và vephai lần lượt là vế trái và vế phải của 1 luật sinh.
- Xây dựng 1 form có tên NPDA) -> (q_CFG nhằm hiển thị các thông tin của NPDA
cho trước và văn phạm (CFG) thu được sau khi chuyển đổi, với đầu vào là file
lưu trữ 1 NPDA dưới dạng text, có tùy biến B)rowse để chọn file chứa NPDA
cần chuyển đổi Tạo các biến cố cần thiết cho các control của form nhằm giải quyết yêu cầu đặt ra của bài toán.
Trang 6III.2 Sơ đồ khối các bước giải quyết công việc
START
Thỏa điều kiện 1
Thỏa điều kiện 2
Chuyển sang CFG
Loại bỏ luật sinh vô dụng
END
Trang 7IV Giao diện chính của chương trình
Trang 8V Phụ lục
publicclass NPDA
{c
publicint q_max; //So trang thai toi da cua NPDA
publicstring xichma = ""; //Cac ky tu ket thuc
publicstring gama = ""; //Cac ky tu chua trong stack
publicint qst = 0; //Trang thai bat dau
publicstring z = "z"; //Ky tu khoi dau stack
publicbool[] F = newbool[100]; //Tap trang thai ket thuc
{c
}
{c
for (int i = 0; i < q_max; i++)
if (F[i])
{c
for (int j = i + 1; j < q_max; j++)
if (F[j])
{c
delta.Add("d(q" + j + ",~,z)>>(q" + i + ",z)");
F[j] = false;
}
break;
}
}
{c
int dcnt = delta.Count;
for (int i = 0; i < dcnt; i++)
Trang 9if (tam.EndsWith(",~)")) //dang 1 (7.5)
continue;
if (tam.Substring(tam.LastIndexOf(",")).Length == 4) //dang 2 (7.6)
continue;
delta.RemoveAt(i);
dcnt ;
i ;
if (tam.Substring(tam.LastIndexOf(",")).Length == 3)
{c
q_max++;
string tam2 = tam.Substring(0, tam.LastIndexOf(">")-1);
string tam3 = tam.Substring(tam.LastIndexOf(">")+1);
string tam4 = tam3.Substring(0, tam3.IndexOf(","));
//Lay bien can thay the
delta.Add(tam2 + ">>(q" + q_max + "," + bien + bien + ")");
delta.Add("d(q" + q_max + ",~," + bien + ")>>" + tam4 + ",~)");
continue;
}
if (tam.Substring(tam.LastIndexOf(",")).Length >= 4)
{c
//Tao them 1 trang thai
q_max++;
string tam2 = tam.Substring(0, tam.LastIndexOf(">")-1);
string tam3 = tam.Substring(tam.LastIndexOf(">")+1);
string tam4 = tam3.Substring(0, tam3.IndexOf(",")-1);
//Lay 2 ky tu cuoi
delta.Add(tam2 + ">>(q" + q_max + "," + tam5 + ")");
dsbien = dsbien.Substring(0, dsbien.Length - 1);
while (true)
{c
if (dsbien.Length <= 2)
break;
//Lay 2 ky tu cuoi
tam5 = dsbien.Substring(dsbien.Length - 2);
delta.Add("d(q" + q_max + ",~," + tam5.Substring(1)+")>>(q"+q_max+","+tam5+ ")");
Trang 10dsbien = dsbien.Substring(0, dsbien.Length - 1);
}
delta.Add("d(q"+ q_max +",~,"+dsbien.Substring(1) + ")>>" + tam4 + "," + dsbien + ")"); continue;
}
}
}
{c
kq.setT(xichma + "~");
this.thoadieukien1();
this.thoadieukien2();
for (int i = 0; i < delta.Count; i++)
{c
string tam = delta[i].ToString();
if (tam.EndsWith(",~)"))
{c
//Ham delta o dang 7.5
//Lay qi
string qi = tam.Substring(2, tam.IndexOf(',') - 2);
//Lay qj
string tam2 = tam.Substring(tam.LastIndexOf(">") + 1);
string qj = tam2.Substring(1, tam2.IndexOf(",")-1);
//Lay ky tu chuyen a
string kta = tam.Substring(tam.IndexOf(",") + 1,1);
//Lay bien dinh Stack A
string bentrai_NPDA = tam.Substring(0, tam.LastIndexOf(">")-1);
string vetrai_ls = "(" + qi + bienA + qj + ")";
string[] vephai_ls = newstring[1];
vephai_ls[0] = kta;
kq.addP(vetrai_ls, vephai_ls);
continue;
}
}
Trang 11if (!tam.EndsWith(",~)"))
{c
//Ham delta o dang 7.6
//Lay qi
string qi = tam.Substring(2, tam.IndexOf(",")-2);
//Lay qj
string tam2 = tam.Substring(tam.LastIndexOf(">") + 1);
string qj = tam2.Substring(1, tam2.IndexOf(",")-1);
//Lay ky tu chuyen a
string kta = tam.Substring(tam.IndexOf(",") + 1, 1);
//Lay bien dinh Stack A
string bentrai_NPDA = tam.Substring(0, tam.LastIndexOf(">")-1);
string haibien = tam.Substring(tam.LastIndexOf(",") + 1, tam.Length -
tam.LastIndexOf(",")-1);
string vetrai_ls = "(" + qi + bienA + qj + ")";
for (int k = 0; k < q_max; k++)
for (int l = 0; l < q_max; l++)
{c
string[] vephai_ls = newstring[3];
vephai_ls[0] = kta;
vephai_ls[1] = "(" + qj + haibien[0] + "q" + l + ")";
vephai_ls[2] = "(q" + l + haibien[1] + "q" + k + ")";
kq.addP(vetrai_ls, vephai_ls);
}
continue;
}
}
int luu = -1;
for (int i = 0; i < q_max; i++)
if (F[i])
{c
luu = i;
break;
}
kq.S = "(q0zq" + luu + ")";
kq.loaiboluatsinhvodung();
return kq;
}
}
Trang 12//Lớp VP: Văn phạm được sinh ra là văn phạm tồn tại với những luật sinh vô dụng
//Ở đây có phương thức loại bỏ những luật sinh vô dụng và được văn phạm rút gọn tương đương
publicclass VP
{c
publicstring T = ""; //T:Tập các ký tự kết thúc
publicstring S = ""; //S:Trạng thái bắt đầu
public VP()
{c
}
publicvoid setT(string T)
{c
this.T = T;
}
{c
if (!this.V.Contains(V_))
this.V.Add(V_);
}
publicvoid addP(string vetrai, string[] vephai)
{c
tam.vetrai = vetrai;
addV(vetrai);
for (int i = 0; i < vephai.Length; i++)
{c
if (vephai[i].StartsWith("("))
addV(vephai[i]);
tam.vephai.Add(vephai[i]);
}
P.Add(tam);
}
{c
Trang 13bienhuudung.Add(((luatsinh)P[i]).vetrai);
else
{c
luu = i;
break;
}
while (true)
{c
bool flag = false;
for (int i = luu; i < P.Count; i++)
{c
luatsinh ls=P[i] as luatsinh;
if(ls==null)
{c
thrownew Exception("ls khong phai la luat sinh");
}
string bien = ls.vetrai;
continue;
{c
flag = true;
bienhuudung.Add(bien);
}
}
if (!flag)
break;
}
for (int i = luu; i < P.Count; i++)
{c
luatsinh ls = P[i] as luatsinh;
if(ls==null)
{c
thrownew Exception("ls khong phai la luatsinh");
}
{c
P.RemoveAt(i);
i ;
continue;
Trang 14}
{c
P.RemoveAt(i);
i ;
continue;
}
}
//Gan lai tap bien
V.Clear();
V = bienhuudung;
}
}
publicclass luatsinh
{c
publicstring vetrai = "";
{c
string str = "";
str += vetrai.ToString() + ">>";
for (int i = 0; i < vephai.Count; i++)
{c
str += vephai[i].ToString();
}
return str;
}
}
Trang 15//Form chính của chương trình
publicpartialclass NPDA_CFG : Form
{c
{c
InitializeComponent();
}
{c
ofd.Title = "Open File";
ofd.InitialDirectory = @"D:\";
ofd.Filter = "Text file(*.txt)|*.txt|All files(*.*)|*.*";
{c
txtPath.Text = ofd.FileName;
}
txtSoTrangThaiMax.Text = reader.ReadLine();
txtTapKyTuKetThuc.Text = reader.ReadLine();
txtTapKyTuStack.Text = reader.ReadLine();
txtTTBatDau.Text = reader.ReadLine();
txtKyTuKhoiDauStack.Text = reader.ReadLine();
txtTapTTKetThuc.Text = reader.ReadLine();
rtxtHamChuyen.Text="";
{c
npda.delta.Add(reader.ReadLine());
}
stream.Dispose();
reader.Dispose();
for (int i = 0; i < npda.delta.Count; i++)
{c
}
npda.q_max = Convert.ToInt32(txtSoTrangThaiMax.Text);
npda.xichma = txtTapKyTuKetThuc.Text;
npda.gama = txtTapKyTuStack.Text;
npda.qst = Convert.ToInt32(txtTTBatDau.Text);
npda.z = txtKyTuKhoiDauStack.Text;
for(int i = 0; i < npda.q_max; i++)
{c
Trang 16npda.F[i] = false;
}
for(int i = 0; i < str.Length; i++)
{c
}
}
{c
VP vp = npda.toVP();
rtxtCFG.Text += "T: " + vp.T.ToString() + "\n";
rtxtCFG.Text += "V: ";
for (int i = 0; i < vp.V.Count; i++)
{c
string str = vp.V[i] asstring;
if (str == null)
{c
thrownew Exception("str khong phai la string");
}
rtxtCFG.Text += (str + " ");
}
rtxtCFG.Text += "\n";
rtxtCFG.Text += "S: " + vp.S.ToString() + "\n\n";
rtxtCFG.Text += "P: \n";
for (int i = 0; i < vp.P.Count; i++)
{c
luatsinh ls = vp.P[i] as luatsinh;
if (ls == null)
{c
thrownew Exception("ls khong phai la luatsinh");
}
rtxtCFG.Text += ls.ToString() + "\n";
}
}
}