Tải bản đầy đủ (.docx) (16 trang)

Báo cáo bài tập lớn automata về dẫn xuất và xuất hiên caay dẫn xuất

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (343.38 KB, 16 trang )

Đồ Án Automat: cho biết dẫn xuất và hiển thị cây dẫn xuất

Phụ Lục
Đặt vấn đề
Ngôn ngữ hình thức (Formal Languages) là môn học cơ sở của ngành
công nghệ thông tin. Nó cho phép nghiên cứu, xây dựng mô hình toán học
cho các máy tính toán. Đặc biệt trong xây dựng mô hình toán cho ngôn ngữ
tự nhiên Kiến thức về ngôn ngữ hình thức và automat là nền tảng cho nhiều
lĩnh vực của khoa học máy tính và CNTT.
Trong nghiên cứu về ngôn ngữ hình thức tập trung vào nghiên cứu các
loại văn phạm. Đó là một tập hợp các quy tắc về cấu tạo từ và quy tắc về cách
thức liên kết lại câu.Bằng cách áp đặt một số hạn chế trên các luật sinh
Chomsky đề nghị một hệ thống phân loại văn phạm dựa vào cấu trúc của các
luật sinh. Bao gồm 4 loại văn phạm là: văn phạm loại 0, văn phạm loại 1, văn
phạm loại 2 và văn phạm loại 3.
Văn phạm phi ngữ cảnh(văn phạm loại 2): là một loại văn phạm khá quan
trọng . Việc nghiên cứu các văn phạm phi ngữ cảnh đã tạo nên một cơ sở lý
luận vững chắc cho việc biểu diễn ngôn ngữ lập trình, việc tìm kiếm các giải
thuật phân tích cú pháp, vận dụng trong chương trình dịch và cho nhiều ứng
dụng khác về xử lý chuỗi. Chẳng hạn, nó rất hữu ích trong việc mô tả các
biểu thức số học với nhiều dấu ngoặc lồng nhau hoặc cấu trúc khối trong
ngôn ngữ lập trình mà biểu thức chính quy không thể đặc tả. Trong văn phạm
1
Đồ Án Automat: cho biết dẫn xuất và hiển thị cây dẫn xuất
phi ngữ cảnh có rất nhiều khâu để xử lý, phân tích. Trong phạm vi của đồ án,
chúng em xin trình bày những cơ sở lý thuyết về văn phạm phi ngữ
cảnh(CFG) đồng thời lập trình đưa ra dẫn xuất và cây dẫn xuất của văn phạm
đã cho.Do lượng kiến thức còn hạn chế nên trong quá trình thực hiện đồ
án còn nhiều thiếu sót mong các thầy đóng góp ý kiến để chúng em
hoàn thiện đồ án.
PHẦN MỘT : CƠ SỞ LÝ THUYẾT


I. VĂN PHẠM PHI NGỮ CẢNH VÀ NGÔN NGỮ PHI NGỮ CẢNH
1.Khái niệm văn phạm.
Văn phạm G là một bộ gồm 4 thành phần G = < Σ, Δ, S, P >, trong đó:
- Σ : bảng chữ cái, gọi là bảng chữ cái cơ bản (bảng chữ cái kết thúc
– terminal symbol);
- Δ , Δ ∩ Σ =Ø, gọi là bảng ký hiệu phụ (bảng chữ cái không kết thúc
– nonterminal symbol);
- S ∈ Δ - ký hiệu xuất phát hay tiên đề (start variable);
- P : tập các luật sinh (production rules) dạng α→β, α, β ∈ (Σ ∪ Δ)*,
trong α chứa ít nhất một ký hiệu không kết thúc (đôi khi, ta gọi
chúng là các qui tắc hoặc luật viết lại).
2.Khái niệm văn phạm phi ngữ cảnh
Định nghĩa:
Một văn phạm phi ngữ cảnh được định nghĩa : G = < Σ, Δ, S, P >
Trong đó:
2
Đồ Án Automat: cho biết dẫn xuất và hiển thị cây dẫn xuất
- Σ : là bảng chữ cái
- Δ : là tập các kí tự không kết thúc (biến)
- S ∈ N là kí tự xuất phát
- P: là tập các luật sinh, mỗi luật sinh có dạng : A ->α
A∈ Δ và α∈ (Δ ∪ Σ)
*
3. Ngôn ngữ phi ngữ cảnh
Định nghĩa: ngôn ngữ L được gọi là ngôn ngữ phi ngữ cảnh nểu tồn tại một
văn phạm phi ngữ cảnh G sao cho L= L( G).
Như vậy : thì một ngôn ngữ chính quy cũng là ngôn ngữ phi ngữ cảnh,
hay nói cách khác lớp các ngôn ngữ chính quy là tập con trong lớp các ngôn
ngữ phi ngữ cảnh.
II. DẪN XUẤT

1. Dẫn xuất trực tiếp và dẫn xuất gián tiếp
Dẫn xuất trực tiếp :Nếu A →b là luật sinh trong văn phạm G và α, β là 2
chuỗi bất kỳ, thì khi áp dụng luật sinh A →b vào chuỗi αAβ ta sẽ thu được
chuỗi αbβ αAβ → αbβ
Dẫn xuất gián tiếp: Giả sử: a
1
→ a
2
, a
2
→ a
3
, , a
m-1
→ a
m
ta viết a
1
→ *a
m
(chú ý rằng a→ *a với mọi chuỗi a)
2. Dẫn xuất trái nhất và dẫn xuất phải nhất
Dẫn xuất trái nhất: Để giới hạn sự lựa chọn các luật sinh trong quá
trình dẫn xuất, nếu mỗi bước biến bên trái nhất của dạng câu được thay thế
thì ta gọi là dẫn xuất trái nhất.
Dẫn xuất phải nhất: Tương tự như dẫn xuất trái nhất nếu mỗi bước biến
bên phải nhất của dạng câu được thay thế thì ta gọi là dẫn xuất phải nhất.
Ví dụ: Xét văn phạm phi ngữ cảnh G = < Σ, Δ, S, P >, trong đó P bao
gồm các luật sinh có dạng:
3

Đồ Án Automat: cho biết dẫn xuất và hiển thị cây dẫn xuất
1.S → aAB; 2.A → bBb; 3.B→ A; 4.B→ ε
S → aAB→ abBbB→abAbB→abbBbbB→abbbbB→abbbb (1)
S → aAB→aA→abBb→abAb→abbBbb→abbbb (2)
Trong đó (1) là đẫn xuất trái nhất, (2) là đẫn xuất phải nhất.
III. CÂY DẪN XUẤT
1. Khái niệm:
Cho văn phạm phi ngữ cảnh G=<Σ, ∆, S, P>. Cây suy dẫn trong văn
phạm G là một cây có gốc thoả mãn năm yêu cầu sau:
- Mỗi nút có một nhãn, là một ký hiệu ∈ (Σ ∪ Δ ∪ {ε} ).
- Nút gốc có nhãn là S (ký hiệu bắt đầu).
- Nếu nút trung gian có nhãn A thì A ∈ Δ .
- Nếu nút n có nhãn A và các đỉnh n
1
, n
2
, , n
k
là con của n theo thứ tự từ
trái sang phải có nhãn lần lượt là X
1
, X
2
, , X
k
thì A
→
X
1
X

2
X
k

một luật sinh trong P.
- Nếu nút n có nhãn là ε thì n phải là nút lá và là nút con duy nhất của
nút cha của nó.
Nếu đọc tất cả nhãn ở các lá theo thứ tự từ trái sang phải, ta sẽ nhận
được một từ nào đó. Từ đó, sẽ là một phần tử trong L(G) và được gọi là kết
quả của cây suy dẫn trong G.
2. Mối quan hệ giữa dẫn xuất và cây dẫn xuất
Cho một văn phạm phi ngữ cảnh G=<Σ, ∆, S, P>, một xâu w được sinh
ra bởi văn phạm. Tồn tại cây dẫn xuất có kết quả là w.
Như vậy: Khi cho một văn phạm phi ngữ cảnh và một xâu w được
sinh ra bởi văn phạm phi ngữ cảnh đó thì ta sẽ xây dựng được cây dẫn xuất
có kết quả là xâu đó.
4
Đồ Án Automat: cho biết dẫn xuất và hiển thị cây dẫn xuất
PHẦN HAI : CẤU TRÚC CHƯƠNG TRÌNH
I. Cấu Trúc Chương Trình
1. Xử lý chuỗi nhập.
Ở đây, sử dụng các hàm để kiểm tra dữ liệu nhập vào khi nhập các
luật sinh . Trong bài , sử dụng 3 hàm để kiểm tra tính thích hợp của dữ
liệu nhập vào. Cụ thể mỗi hàm có tác dụng như sau :
- Hàm thứ 1 là : Hàm KiemTraDL(string t, string[] s) cho phép ta sử dụng
để kiểm tra xâu t có nằm trong tập xâu s hay không. Cụ thể trong bài
dùng để kiểm tra dữ liệu nhập vào của luật sinh, xem có thuộc tập kí
hiệu phụ hay không.

public static bool KiemTraDL(string t, string[] s)

{
int ok = 0;
for (int i = 0; i < s.Length; i++)
if (t == s[i])
{
ok = 1;
break;
}
if (ok == 1)
return true;
else
return false;
}
- Hàm thứ 2 là :KTDLSAU() để kiêm tra xâu dẫn xuất sinh ra từ kí hiệu
phụ các phần tử có thuộc tập kí hiệu phụ hay bảng chữ cái hay không.
Áp dụng trong bài để kiểm tra việc nhập vào luật sinh có đúng các kí tự
cho phép hay không. Cụ thể hàm như sau :
public bool KTDLSAU()
{
int ok1 = 1;
string s = txtsau.Text;
ttsau = new string[s.Length];
for (int i = 0; i < s.Length; i++)
ttsau[i] = s.Substring(i, 1);
for (int i = 0; i < ttsau.Length; i++)
if (!KiemTraDL(ttsau[i], chucai)
&& !KiemTraDL(ttsau[i], kihieuphu))
{
ok1 = 0;
5

Đồ Án Automat: cho biết dẫn xuất và hiển thị cây dẫn xuất
break;
}
if (ok1 == 0)
return false;
else
return true;
}
- Hàm thứ 3 là : Hàm KT(string t) để kiểm tra 1 chuỗi t có chứa kí hiệu
trong bảng kí hiệu phụ hay không . Cụ thể trong bài vận dụng để kiểm tra
dẫn xuất sinh bởi một kí hiệu phụ có chứa kí hiệu phụ hay không vận
dụng vào để vẽ cây và tìm đẫn xuất. Cụ thể hàm như sau :
public static bool KT(string t)
{
string[] m = new string[t.Length];
int k = 0;
for (int i = 0; i < t.Length; i++)
{
m[i] = t.Substring(i, 1);
if (KiemTraDL(m[i], kihieuphu))
k = 1;
}
if (k == 1)
return true;
else
return false;
}
2. In ra dẫn xuất.
Sau khi đã kiểm tra được sự thích hợp của dữ liệu đầu vào, thì yêu
cầu của bài là in ra dẫn xuất. Trong bài, có sử dụng 1 hàm xulychuoi()

để lưu các trạng thái dẫn xuất của từng kí hiệu phụ ở đây em dùng 1
mảng hai chiều để lưu. Chỉ số hàng tương ứng với chỉ số của kí hiệu phụ
sinh ra dẫn xuất đó, các phần tử trong cùng một hàng là các dẫn xuất
được in ra từ kí hiệu phụ có chỉ số là chỉ số của hàng. Cụ thể hàm
xulychuoi() như sau :
public void xulychuoi()
{
luatsinh = txtLuatSinh.Text.Split('\n');
bdoi = new string[kihieuphu.Length, luatsinh.Length - 1];
bdoi1 = new string[kihieuphu.Length, luatsinh.Length - 1];
for (int i = 0; i < luatsinh.Length - 1; i++)
6
Đồ Án Automat: cho biết dẫn xuất và hiển thị cây dẫn xuất
{
string[] p1 = new string[luatsinh[i].Length];
p1 = luatsinh[i].Split('-', '>');
for (int m = 0; m < kihieuphu.Length; m++)
{
if (p1[0] == kihieuphu[m])
{
if (p1[p1.Length - 1] != null)
bdoi[m, i] = p1[p1.Length - 1];
else
bdoi[m, i] = null;
bdoi1[m, i] = bdoi[m, i];
}
}
}
}
Sau đó, ta dùng những kết quả thực hiện ở các bước trên đi xây

dựng giải thuật tìm ra dẫn xuất. Ở đây em sử dụng dẫn xuất trái nhất,
duyệt từ trái sang của chuỗi dẫn xuất nếu gặp kí tự là kí hiệu phụ thì
dừng lại tìm vào mảng 2 chiều nếu như luật sinh từ kí hiệu đó khác null
thì thay kí hiệu phụ đó bằng luật sinh đó. Cứ thực hiện như vậy, cho tới
khi nào dẫn xuất sinh ra chỉ chứa kí hiệu nằm trong bảng chữ cái thì
dừng lại. Cụ thể giải thuật đó được cụ thể hóa bằng đoạn mã sau:
private void btnXuat_Click_1(object sender, EventArgs e)
{
xulychuoi();
bdoi[0, 0] = bdoi1[0, 0] = null;
s = luatsinh[0];
string[] p2 = s.Split('-', '>');
string c = p2[p2.Length - 1];
try
{
lap:
while (KT(c))
{
string d = null;
for (int i = 0; i < c.Length; i++)
{
for (int m = 0; m < bdoi.GetLength(0); m++)
{
if (Convert.ToString(c[i]) == kihieuphu[m])
{
for (int l = 0; l < bdoi.GetLength(1); l++)
7
Đồ Án Automat: cho biết dẫn xuất và hiển thị cây dẫn xuất
{
if (bdoi[m, l] != null)

{
string f1 = c.Substring(0, i);
string f2 = bdoi[m, l];
string f3 = c.Substring(c.IndexOf(c[i]) + 1);
d += f1 + f2 + f3;
s += "->" + d;
if (KT(bdoi[m, l]))
{
bdoi[m, l] = null;
}
c = d;
goto lap;
}
else
continue;
}
break;
}
else
continue;
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
Form2 fr = new Form2();
fr.Show();

}
3. Vẽ cây
Sau khi đã có được dẫn xuất, yêu cầu tiếp theo là vẽ cây dẫn xuất.
để vẽ được cây ta xây dựng lớp Nut, mỗi đối tượng có đầy đủ : tọa độ,
màu, tên của nó chính là kí hiệu em sẽ vẽ lên nút đó, trong đó có phương
thức nối để nối 2 nút với nhau dùng Line. Dùng graphics để vẽ , cụ thể
lớp Nut được xây dựng như sau :
8
Đồ Án Automat: cho biết dẫn xuất và hiển thị cây dẫn xuất
class Nut
{
public float x;
public float y;
public string Ten;
public Color color;
private Graphics myG;
public Nut(Graphics g)
{
myG = g;
color = Color.Red;
}
public void Ve()
{
myG.DrawEllipse(new Pen(color, 2), x, y, 30, 30);
myG.FillEllipse(new SolidBrush(Color.YellowGreen), x, y,
30, 30);
myG.DrawString(Ten, new Font("Arial", 11,
FontStyle.Bold), new SolidBrush(color), x + 5, y + 5);
}
public void noi(Nut N1, Nut N2)

{
N1.Ve();
N2.Ve();
myG.DrawLine(new Pen(color, 2), N1.x + 20, N1.y +
29, N2.x + 4, N2.y + 4);
}
}
Dùng lớp Caycon để vẽ những cây của nut trung gian và nút gốc sau đó
ghép chúng lại để thành cây. Cụ thể code vẽ cây con như sau :
class caycon
{
public static int sonutcon = 0;
public static Nut[] dsnut;
public static Nut nutgoc;
public static void ve(string s, Graphics g, Nut t)
{
nutgoc = t;
dsnut = new Nut[s.Length];
for (int i = 0; i < s.Length - 1; i++)
{
dsnut[i] = new Nut(g);
dsnut[i].Ten = Convert.ToString(s[i]);
dsnut[i].y = nutgoc.y + 70;
if (i < (sonutcon + 1) / 2)
9
Đồ Án Automat: cho biết dẫn xuất và hiển thị cây dẫn xuất
{
dsnut[i].x = nutgoc.x - 50 * (i);
}
else

{
dsnut[i].x = nutgoc.x + 50 * (i - (sonutcon) /
2);
}
nutgoc.noi(nutgoc, dsnut[i]);
}
}
}
Sử dụng lớp Nut và lớp Caycon tren để vẽ cây dẫn xuất trong lớp
Vecay sử dụng dữ liêu trực tiếp từ Form Nhập. Giải thuật vẽ cây được
thể hiện rõ bởi đoạn mã dưới đây :
class Vecay
{
public string[] Bluatsinh = frmNhap.luatsinh;
public string[,] Bbdoi = frmNhap.bdoi1;
public string[] KHphu = frmNhap.kihieuphu;
#region Vẽ cây
public void vecaydx(Graphics g)
{
string chuoi1 = Bluatsinh[0];
string[] split1 = chuoi1.Split('-', '>');
Nut n1 = new Nut(g);
string ss1;
int dem;
n1.Ten = split1[0];
n1.x = 200;
n1.y = 100;
caycon.ve(split1[split1.Length - 1], g, n1);
ss1 = split1[split1.Length - 1];
while (frmNhap.KT(ss1))

{
ss1 = "";
Nut[] arrnut1 = new Nut[100];
for (int i = 0; i < caycon.dsnut.Length; i++)
{
arrnut1[i] = new Nut(g);
arrnut1[i] = caycon.dsnut[i];
}
try
{
lap:
10
Đồ Án Automat: cho biết dẫn xuất và hiển thị cây dẫn xuất
Nut[] arrnut = arrnut1;
dem = 0; arrnut1 = new Nut[100];
for (int i = 0; i < arrnut.Length; i++)
{
for (int j = 0; j < KHphu.Length; j++)
if (arrnut[i].Ten == KHphu[j])
{
n1 = arrnut[i];
for (int k = 0; k < Bbdoi.GetLength(1); k++)
{
if (Bbdoi[j, k] != null)
{
caycon.ve(Bbdoi[j, k], g, n1);
if (frmNhap.KT(Bbdoi[j, k]))
{
ss1 += Bbdoi[j, k];
Bbdoi[j, k] = null;

goto lap;
}
for (int p = 0; p < caycon.dsnut.Length; p++)
{
arrnut1[dem] = new Nut(g);
arrnut1[dem] = caycon.dsnut[p];
dem++;
}
}
}
}
}
catch
{
;
}
}
}
#endregion
}
Trên đây là toàn bộ những đoạn mã, đoạn code chính sử dụng để thực
hiện yêu cầu của bài toán.
11
Đồ Án Automat: cho biết dẫn xuất và hiển thị cây dẫn xuất
II. Sơ Đồ Khối Của Chương Trình
III. Các Giao Diện Chính
12
Start
Nhập dữ liệu
cần thiết

Kiểm tra dữ liệu
y
e
No
In ra chuỗi dẫn
xuât
In ra cây dẫn
xuất
End
Đồ Án Automat: cho biết dẫn xuất và hiển thị cây dẫn xuất
Khi chạy chương trình sẽ xuất hiện một form để cho phép lựa chọn các
chức năng:
H1-Giao diện Form chính
Có 2 lựa chọn:
- Nếu chọn phím Exit : thì sẽ thoát khỏi chương trình.
- Nếu chọn Chose: thì sẽ hiển thị Form Nhập cho phép nhập vào các
thông tin về văn phạm. Form Nhập: người sử dụng phải nhập tất cả
các thông tin cần thiết liên quan tới văn phạm như: nhập vào bảng
chữ cái Σ, nhập vào bảng các kí hiệu phụ ∆. Sau đó, nhập vào các luật sinh
trong P: ấn vào nút Thêm để thêm luật sinh vào P, ấn nút Mới để thiết lập luật
sinh mới.
13
Đồ Án Automat: cho biết dẫn xuất và hiển thị cây dẫn xuất

H2-Giao diện Form nhập
- Chú ý: nếu nhập vào luật sinh mà sai không phải là các kí hiệu trong bảng chữ
cái hoặc bảng kí hiệu phụ thì sẽ báo lỗi. Ví dụ:
H3- Form Báo Lỗi
Sau khi đã nhập đầy đủ thông tin về văn phạm, ấn nút Dẫn Xuất
sẽ xuất hiện Form Hiển Thị. Trên màn hình Form hiển thị sẽ xuất

hiện trên textbox dãy sinh ra dẫn xuất. Nếu ấn nút Hiển thị cây trên
Form Hiển Thị sẽ vẽ lên màn hình Form hiển thị cây dẫn xuất được
sinh bởi văn phạm đã cho.
14
Đồ Án Automat: cho biết dẫn xuất và hiển thị cây dẫn xuất
H4 –Hiển thị dẫn xuất, Cây
Danh mục tài liệu tham khảo:
1.Bài giảng Automat và ngôn ngữ hình thức – Ts.Nguyễn Văn Định- khoa
CNTT
2. Slide bài giảng Automat – Ts.Hà Chí Trung - HVKTQS
15

×