^Back To Top
Một trong những mục tiêu lớn và quan trọng của trí tuệ nhân tạo (TTNT) là mô phỏng trên máy tính những tư duy và hành vi của con người. Ngôn ngữ lập trình Prolog chuyên dùng trong lĩnh vực TTNT, một dạng lập trình ngôn ngữ phi thủ tục, cho phép hướng tới xử lý và lập trình logic và xử lý ngôn ngữ tự nhiên sang ngôn ngữ máy.
1. Giới thiệu
Một trong những mục tiêu lớn và quan trọng của trí tuệ nhân tạo (TTNT) là mô phỏng trên máy tính những tư duy và hành vi của con người. Trước những năm 1960, khi chưa có nhóm các ngôn ngữ lập trình (NNLT) chuyên phục vụ cho lĩnh vực TTNT như các NNLT xử lý ký hiệu (LISP- LISt Processing) và lập trình lôgic (PROLOG – PROgramming in LOGic), những thành tựu lý thuyết trong TTNT chưa được ứng dụng rộng rãi trong thực tế.
NNLT Prolog do Alain Colmerauer và nhóm cộng sự thiết kế ra vào năm 1972 tại đại học Marseille ở Pháp. Prolog được xây dựng trên cở sở lý thuyết của lôgic vị từ, nhằm biểu diễn, mô tả các tri thức cùng các mối quan hệ cơ bản giữa chúng. Từ đó, khi đã được trang bị sẵn một cơ chế suy luận thông qua một môtơ suy diễn, Prolog sẽ sản sinh ra và kiểm tra nhiều mối quan hệ hệ quả khác.
Ví dụ: Để mô tả các sự kiện (fact): “Socrate và Tèo là người”, qui tắc lôgic (hoặc luật, rule): “hễ bất cứ ai là người thì người đó sẽ phải chết”, ta dùng hai vị từ chính: LàNgười(Ai), Chết(Ai) như sau:
LàNgười(“Socrate”).
LàNgười(“Tèo”).
Chết(Ai) :- LàNgười(Ai).
//hoặc: Chết(Ai) if LàNgười(Ai).
Dựa trên các tri thức vừa mô tả, ta có thể yêu cầu Prolog trả lời các câu hỏi liên quan sau:
hoặc:
Các khái niệm chính trong Prolog là: vị từ (predicate), đối tượng, biến, sự kiện (fact), qui tắc (rule), câu hỏi (đích, mục tiêu: Goal), danh sách. Vài kỹ thuật thường được dùng trong Prolog là: quay lui (mặc định là tìm kiếm theo chiều sâu trên cây suy diễn), đệ qui, lát cắt.
2. Cấu trúc chính của một chương trình trong Prolog
Một chương trình của Prolog thường bao gồm một số các phần chính và theo thứ tự sau:
Constants % Đoạn khai báo các đối tượng hằng
Domains % Đoạn khai báo kiểu các đối tượng riêng của người dùng
Database % Đoạn khai báo kiểu cho các vị từ của cơ sở dữ liệu
Predicates % Đoạn khai báo kiểu cho vị từ sẽ dùng trong các đoạn sau
Clauses % Đoạn liệt kê sự kiện và định nghĩa qui tắc đã khai báo trong phần Predicates
Goal % Đoạn đưa vào các vị từ câu hỏi, có thể đặt trước phần Clauses
Chú ý: Một chương trình có thể thiếu một số (hoặc tất cả !) phần trên.
3. Ứng dụng ngôn ngữ lập trình Prolog trong một số bài toán Trí tuệ nhân tạo
3.1. Bài toán “Tháp Hà Nội” (Minh họa vị từ đệ qui)
Ví dụ 1: Có 3 cọc A, B, C. Trên cọc A có n đĩa tròn chồng lên nhau, với đường kính khác nhau, sao cho đĩa bé luôn nằm trên đĩa lớn; hai cọc B, C trống. Tìm cách chuyển n đĩa từ A đến C với số lần di chuyển đĩa ít nhất (2n-1), sao cho: mỗi lần chỉ di chuyển 1 đĩa bé nhất trên cùng của một cọc tùy ý sang một cọc khác để đĩa bé luôn nằm trên đĩa lớn.
%Program Thap_HaNoi
Domains
i = integer
s = symbol
Predicates
HaNoi(i, i)
ChuyenDia(i, i, s, s, s, i)
Clauses
HaNoi(N, SoLanDiChuyen) :- ChuyenDia(N, N, a, c, b, SoLanDiChuyen).
ChuyenDia(1, Nhan, Tu, Den, _, 1) :- !, nl,
write(“Chuyen dia: “, Nhan, “ tu “, Tu, “ den “, Den).
ChuyenDia(N, Nhan, Tu, Den, Tgian, Tong):-
N1=N-1, NhanPhu=Nhan-1,
ChuyenDia(N1, NhanPhu, Tu, TGian, Den, Tong1),
ChuyenDia(1, Nhan, Tu, Den, Tgian, 1),
ChuyenDia(N1, NhanPhu, TGian, Den, Tu, Tong2),
Tong = Tong1 + Tong2 + 1.
Goal %trong
makewindow(1, 3, 7, “Thap Ha Noi”, 0, 0, 25, 80),
write(“Nhap so dia n (1<=n<=12): “), readint(N), HaNoi(N, Tong),
write(“Tong so lan di chuyen dia: “, Tong)..
Kết quả của chương trình với n=2 là:
Chuyen dia: 1 tu a den b
Chuyen dia: 2 tu a den c
Chuyen dia: 1 tu b den c
Tong so lan di chuyen dia: 3
3.2. Bài toán suy luận lôgic (Minh họa lập trình cho bài toán lập luận lôgic)
Ví dụ 2: Trên một đảo nọ, chỉ có hai nhóm người: một nhóm chỉ gồm những người luôn nói thật và nhóm còn lại chỉ gồm những người luôn nói láo. Một nhà thông thái đến đảo này và gặp ba người A, B, C. A nói: “Trong ba người chúng tôi chỉ có đúng một người nói thật”, C nói: “Cả ba người chúng tôi đều nói láo”. Hỏi trong ba người A, B, C, ai nói thật, ai nói láo ?
Ta biểu diễn mỗi phương án của bài toán bằng danh sách [A, B, C], sao cho mỗi phần tử chỉ gồm một trong hai trạng thái 0, 1, tương ứng với trạng thái nói láo hoặc nói thật. Ta mô tả câu nói của A và C như sau: nếu A nói thật thì Tổng = A+B+C = 1, nếu A nói láo thì Tổng ≠ 1; nếu C nói thật thì Tổng = A+B+C = 0, nếu C nói láo thì Tổng > 0.
%Program Noi lao, noi that
Domains
i, ptu = integer
ds = ptu*
Predicates
TaoDS(i,ds)
Quet(ptu)
Giai(i,ds)
SuKien(symbol,ds)
Tong(ds,integer)
Viet(ds,i)
Clauses
Quet(0).
Quet(1).
TaoDS(N,[]) :- N <= 0, !.
TaoDS(N,[Dau|Duoi]) :- Quet(Dau),N1 = N - 1, TaoDS(N1,Duoi).
Giai(N,DS) :- TaoDS(N,DS), SuKien("A",DS), SuKien("C",DS).
SuKien("A",DS) :- DS = [1,_,_], Tong(DS,1).
SuKien("A",DS) :- DS = [0,_,_], Tong(DS,So), So <> 1.
SuKien("C",DS) :- DS = [_,_,1], Tong(DS,0). % phi li !
SuKien("C",DS) :- DS = [_,_,0], Tong(DS,So), So > 0.
Tong([],0) :- !.
Tong([Dau|Duoi],Kq) :- Tong(Duoi,KqDuoi), Kq = KqDuoi + Dau.
Viet([],_) :- nl,!.
Viet([1|D],I):-!,I1=I+1,I2 =I1+64,char_int(C,I2), write(C," noi that\n"), Viet(D,I1).
Viet([0|D],I):-!,I1=I+1,I2 =I1+64,char_int(C,I2), write(C," noi lao\n"), Viet(D,I1).
Goal % trong
Giai(3,DS),Viet(DS,0),nl.
Kết quả của chương trình là:
A noi that
B noi lao
C noi lao
Khác với nhiều ngôn ngữ lập trình (NNLT) thủ tục cổ điển truyền thống, Prolog thuộc nhóm NNLT mô tả. Để giải quyết một bài toán, đặc biệt là các bài toán xử lý ký hiệu trừu tượng và suy luận lôgic, chỉ cần chọn cách biểu diễn phù hợp và mô tả các đối tượng cùng các tính chất và mối quan hệ cơ bản đã biết giữa chúng. Thông qua môtơ suy diễn của Prolog, sẽ nhận được các câu trả lời liên quan đến các mối quan hệ nhân quả và các kết luận liên quan đến bài toán cần giải quyết. Khi tri thức đã biết về bài toán không tăng thêm, việc trả lời các kết luận khác liên quan đến bài toán cần giải là hiển nhiên thông qua các câu hỏi thêm mà không cần phải lập trình lại như các NNLT kiểu thủ tục. Chính vì vậy, NNLT Prolog thuộc kiểu hội thoại và một chương trình nguồn trong Prolog thường gọn hơn rất nhiều so với một chương trình nguồn của các NNLT thủ tục truyền thống khác như Pascal, C, … nhằm cùng giải quyết một bài toán chuyên biệt trong lĩnh vực TTNT.