Ngôn ngữ lập trình prolog
Contents
1. Prolog là gì?
Prolog là ngôn ngữ được sử dụng phổ biến trong lĩnh vực trí tuệ nhân tạo. Nguyên lý lập trình logic dựa trên các mệnh đề Horn (Horn logíc).
2. Những thứ cơ bản của Prolog
Bạn có thể code prolog online tại: https://swish.swi-prolog.org/
2.1 Cú pháp
Tên_hàm(tham số 1, tham số 2,..., tham số n)
2.2 Các toán tử
Toán tử | Kí hiệu |
if | :- |
and | , |
or | ; |
not | not |
khác | =\= |
bằng | =:= |
ghi chú | % or /**/ |
dừng câu lệnh | ! |
kết thúc câu lệnh | . |
phép cộng | + |
phép trừ | – |
phép nhân | * |
phép chia | / |
Chia lấy dư | x mod y |
gán giá trị | is |
ngắt dòng | nl |
Ví dụ:
cha(nam, khoi). con(X,Y) :- cha(Y,X).
Code trên được hiểu như sau:
- con(X,Y): là mệnh đề then
- cha(Y,X): là mệnh đề if
- Nếu Y là cha của X thì X là con của Y.
2.3 Suy diễn
GỒM 2 LOẠI:
- Suy diễn tiến: từ nút gốc => nút lá hay từ đề bài đến kết quả
- Suy diễn lùi: từ nút lá => nút gốc hay từ kết quả đến đề bài.
Suy diễn lùi nhanh hơn suy diễn tiến, vì:
- Suy diễn tiến liệt kê toàn bộ các nút
- Suy diễn lùi chỉ làm 1 nhánh.
Phương pháp tìm kiếm thăm dò:
- Theo chiều rộng:
– OPEN: đã phát sinh nhưng chưa được mở rộng (chưa được duyệt qua).
– CLOSED: đã được duyệt qua
Ví dụ:
Giải thuật:
- 1. OPEN = [A]; CLOSED = []
- 2. OPEN = [B, C, D]; CLOSED = [A]
- 3. OPEN = [C, D, E, F]; CLOSED = [B, A]
- 4. OPEN = [D, E, F, G, H]; CLOSED = [C,B, A]
- 5. OPEN = [E, F, G, H, I, J]; CLOSED = [D, C, B, A]
- 6. OPEN = [F, G, H, I, J, K, L]; CLOSED = [E, D, C, B, A]
- 7. OPEN = [G, H, I, J, K, L, M]; CLOSED = [F, E, D, C, B, A]
- 8. OPEN = [H, I, J, K, L, M, N]; CLOSED = [G, F, E, D, C, B,A]
- 9. and so on until either U is found or OPEN is empty.
- Theo chiều sâu:
Logic mờ là gì?
http://blog.thanhnt.com/cach-hieu-don-gian-ve-logic-mo-fuzzy-logic/
2.4 Những bài tập đầu tiên
tongcong([], 0):-!. tongcong([D|C], Kq):-tongcong(C, Kq1), Kq is Kq1+D, !. dem([], 0):-!. dem([_|C], KQ):-dem(C, KQ1), KQ is KQ1 + 1, !. tongchan([], 0):-!. tongchan([D|C], KQ):- D mod 2 =:= 0, tongchan(C, KQ1), KQ is KQ1 + D, !. tongchan([_|C], KQ):-tongchan(C,KQ). tongle([], 0):-!. tongle([D|C], KQ):- D mod 2 =\= 0, tongle(C, KQ1), KQ is KQ1 + D, !. tongle([_|C], KQ):-tongle(C,KQ). boPhanTuDau([], []):- !. boPhanTuDau([_|C], C):-!.
%/ten ham viet thuong, ten bien viet hoa chu cai dau %Bai 1: tim phan tu thu nhat timphantuthunhat([],[]). timphantuthunhat([Dau|_],Dau). %Bai 2: tim phan tu thu 2 timphantuthuhai([],[]). timphantuthuhai([_],[]):-!. timphantuthuhai([_,Y|_],Y). %Bai 3: tim phan tu cuoi cung timphantucuoi([],[]). timphantucuoi([Cuoi],Cuoi):-!. timphantucuoi([_|Cuoi],Kq):-timphantucuoi(Cuoi,Kq). %bai 4: xoa phan tu dau tien remove([],_,[]). remove([Dau|Cuoi],Dau,Cuoi):-!. remove([Dau|Cuoi],Phantucanxoa,[Dau|Kq]):-remove(Cuoi,Phantucanxoa,Kq). %bai 5: xoa tat ca phan tu trung trong danh sach removeall([],_,[]). removeall([Dau|Cuoi],Dau,Kq):-removeall(Cuoi,Dau,Kq),!. removeall([Dau|Cuoi],Phantucanxoa,[Dau|Kq]):-removeall(Cuoi,Phantucanxoa,Kq).
amtiet(amtiet(Dau,Giua,Cuoi)) --> dau(X, Dau), giua(X, Y, Giua), cuoi(Y, Cuoi). %amtiet(Giua,Cuoi) --> giua(Giua), cuoi(Cuoi). %amtiet(Giua) --> giua(Giua). %amtiet(Dau,Giua) --> dau(Dau), giua(Giua). % ------------------------------------------------------------------------ dau(X, dau(P1)) --> p1(X, P1). giua(X, Y, giua(N1)) --> n1(X, Y, N1). cuoi(Y, cuoi(P4)) --> p4(Y, P4). cuoi(Y, cuoi(P4,P5)) --> p4(Y, Z, P4), p5(Z, P5). % ------------------------------------------------------------------------ p1(n, p1(n)) --> [n]. p1(m, p1(m)) --> [m]. n1(X, Y, n1(a)) --> [a], {(X = n, Y = m); (X = n, Y = n)}. n1(X, Y, n1(i)) --> [i], {X = m, Y = n}. p4(m, p4(m)) --> [m]. p4(n, Z, p4(n)) --> [n], {Z = g; Z = h}. p5(g, p5(g)) --> [g]. p5(h ,p5(h)) --> [h].
3. Kết hợp C# và Prolog
Bước 1: click phải chuột vào References => Add Reference
Bước 2: Click Browser cạnh nút ok
Bước 3: Chọn 2 file:
- nunit.framework.dll
- SwiPlCs.dll
Khi chọn xong click ok
Bước 4: Copy toàn bộ file download và ghi đè vào thư mục bin/debug
Bước 5: Add Class XuLy
Bước 6: Copy nội dung vào file XuLy (Lưu ý chỉ copy thư viện và nội dung class để tránh bị lỗi)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using SbsSW.SwiPlCs; //ket noi voi prolog using System.Text.RegularExpressions; using NUnit.Framework; namespace Test { class XuLy { //Load prolog file from hard disk public void Load_file(string s) { s = s.Replace("\\", "//"); s = "consult('" + s + "')"; string query = s.Replace("\\", "//"); //string[] p = { "-q", "-f", query }; //PlEngine.Initialize(p); try { PlQuery q = new PlQuery(query); Assert.IsTrue(q.NextSolution()); } catch (SbsSW.SwiPlCs.Exceptions.PlException e) { System.Windows.Forms.MessageBox.Show(e.ToString(), "Error"); } } // Prosessing a query public string Query(string s) { s.Trim(); Regex r = new Regex(@"[A-Z_][a-zA-Z_]*"); MatchCollection matches = r.Matches(s); string result = ""; try { PlQuery q = new PlQuery(s); bool HasSolution = false; foreach (PlQueryVariables v in q.SolutionVariables) { HasSolution = true; foreach (Match match in matches) { result += v[match.ToString()].ToString() + " ; "; } } if (matches.Count == 0) return HasSolution ? "true" : "false"; return result; } catch (SbsSW.SwiPlCs.Exceptions.PlException ex) { return "Error query: " + ex.Message; } } } }
Bước 7: Mở file program.cs (ở góc trên bên phải) sửa lại thư viện và nội dung hàm Main
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; using SbsSW.SwiPlCs; //thu vien ket noi prolog using NUnit.Framework; using System.Text.RegularExpressions; namespace Test { static class Program { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { Environment.SetEnvironmentVariable("SWI_HOME_DIR", @"C:\Program Files\swipl"); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); if (!PlEngine.IsInitialized) { String[] empty_param = { "" }; PlEngine.Initialize(empty_param); Application.Run(new Form1()); PlEngine.PlCleanup(); } } } }
Bước 7: Thiết kế form
- khung nhập đầu: txtinput (Name)
- button
- Khung nhập sau: txtoutpout
Bước 8: Click phải vào form chọn View Code
Bước 8.1: Thêm thuộc tính connect và tạo đối tượng trong constructor của form
XuLy connect; public Form1() { connect = new XuLy(); InitializeComponent(); }
Bước 8.2: Sự kiện form_load
private void Form1_Load(object sender, EventArgs e) { OpenFileDialog op = new OpenFileDialog(); op.Filter = "Prolog file|*.pl"; op.ShowDialog(); String FilePath = op.FileName; connect.Load_file(FilePath); MessageBox.Show("Load file success !"); }
Bước 8.3: Sự kiện button_click
private void button1_Click(object sender, EventArgs e) { if (this.txtinput.Text != null) { //Chuyển textBox1.txt sang câu truy vấn String s = connect.Query(changestring()); this.txtoutput.Text = s; //this.txtTree.Text = s; } else { MessageBox.Show("Please enter query !"); } }
Bước 8.3: Thêm hàm chuyển
// ham chuyen public string changestring() { string s = "timdautien(["; string dulieu = txtinput.Text; string[] chuoi = dulieu.Split(new Char[] { ' ' }); for (int i = 0; i < int.Parse(chuoi.Length.ToString()); i++) { s = s + chuoi[i]; if (i != int.Parse(chuoi.Length.ToString()) - 1) s = s + ','; } s = s + "],Kq)."; return s; }
Đây là hàm bạn cần thay thế để chạy lệnh của prolog
4. Mẹo sử dụng IDE
- Khi chạy bị lỗi. Nhấn Ctrl + Z để thoát ra.
5. Viết chương trình âm tiết tiếng việt
s(s(NP,VP))-->np(NP),vp(VP). np(np(NNP))-->nnp(NNP). np(np(CD, N_UNIT, NN))-->cd(CD),n_unit(N_UNIT),nn(NN). np(np(N_UNIT, NN, ADJP))-->n_unit(N_UNIT), nn(NN), adjp(ADJP). np(np(NN))-->nn(NN). np(np(PRP))-->prp(PRP). np(np(CD, NP))-->cd(CD), np(NP). adjp(adjp(JJ))-->jj(JJ). adjp(adjp(RB,JJ))-->rb(RB), jj(JJ). jj(jj(do))-->[do]. jj(jj(rong))-->[rong]. rb(rb(rat))-->[rat]. rb(rb(thuong))-->[thuong]. rb(rb(hay))-->[hay]. vp(vp(VB, NP))-->vb(VB),np(NP). vp(vp(RB, VB, PP))-->rb(RB), vb(VB), pp(PP). vp(vp(RB, VB, NP))-->rb(RB), vb(VB), np(NP). vb(vb(mua))-->[mua]. vb(vb(o))-->[o]. vb(vb(co))-->[co]. vb(vb(ngoi))-->[ngoi]. vb(vb(doc))-->[doc]. pp(pp(IN, NP))-->in(IN), np(NP). in(in(ngoai))-->[ngoai]. cd(cd(mot))-->[mot]. n_unit(n_unit(can))-->[can]. n_unit(n_unit(cai))-->[cai]. nn(nn(nha))-->[nha]. nn(nn(ngoai, o))--> [ngoai, o]. nn(nn(san))-->[san]. nn(nn(truyen))-->[truyen]. nnp(nnp('Nam'))-->['Nam']. prp(prp(no))-->[no].
Một vài lưu ý:
- Các hàm giống nhau phải đặt gần nhau. Vd: vb, np
- Nếu dữ liệu có kí tự hoa ở đầu phải bỏ trong dấu nhay đơn. Vd: ‘Nam’
Từng bước thực hiện:
Ví dụ:
Ta thấy:
- Nút s có 2 nút con là np và vp. Ta viết: s–>np,vp.
- Nút np có 1 nút con là nnp. Ta viết: np->nnp.
- Nút nnp có 1 nút con là Nam. Ta viết: nnp–>[‘Nam’].
- Tương tự với các nút khác ta được kết quả sau.
s-->np, vp. np-->nnp. np-->cd, n_unit, nn. vp-->vb, np. nnp-->['Nam']. vb-->[mua]. cd-->[mot]. n_unit-->[can]. nn-->[nha].
Lưu kết quả trên thành file *.pl (* là tên bạn đặt)
Nạp file vào prolog gõ lệnh sau sẽ ra true.
s(['Nam', mua, mot, can, nha], []).
Từ đoạn code trên tiến hành làm thêm các bước:
- s–>np,vp. Thêm biến vào S và vế phải, vế trái phải gọi lại tên của nó.
s(s(NP,VP))-->np(NP),vp(VP).
Làm tương tự với các dòng còn lại. Các câu khác cũng làm tương tự nhưng cái này bị trùng thì không cần phải viết lại.
Có thể tham khảo thêm tại: https://ohmygodit.wordpress.com/2014/03/06/127/