Bài toán suy diễn
Trang 1Các bài toán có yếu tố suy diễn
Nguyễn Xuân Huy
Trong lĩnh vực trí tuệ nhân tạo ta thường gặp một số bàitoán tin có chứa các yếu tố suy diễn theo kiểu nếu X suy ra Y và Y suy ra Z thìX cũng suy ra Z Các bài toán thuộc loại này không khó lắm, tuy nhiên chúngthường đòi hỏi một số nhận xét tinh tế nhằm rút ngắn quá trình suy diễn Chúngta thử trình bày một cách giải vài bài thuộc loại này:
Bài toán Tham quan Một lớp học có n học sinh mang tên A, B, C Giữa các nhóm họcsinh
có một số quan hệ tạm gọi là quan hệ ảnh hưởng, thí dụ, nếu ta viết AB> C thì có nghĩa là hai bạn A và B đồng thời cùng thuyết phục thì có thể yêucầu bạn C tham gia một hoạt động nào đó cùng với mình Cho biết m quan hệ giữacác nhóm học sinh trong lớp Giả sử một nhóm X của lớp muốn rủ các bạn cùng lớpđi tham quan thành Cổ Loa chẳng hạn Hãy cho biết những bạn nào sẽ có mặt trongnhóm tham quan đó
Dữ liệu vào ghi trong tệp văn bản THAMQUAN.INP với cấu trúc như sau:
* Dòng đầu tiên: hai số tự nhiên n và m biểu thị sốhọc sinh trong lớp và số các quan hệ, 2
=< n =< 26, 1 =< m =<50
* Tiếp theo là m dòng, mỗi dòng biểu thị một quan hệdạng X > Y
* Dòng cuối cùng là danh sách các học sinh trongnhóm X
Hiển thị trên màn hình danhsách các học sinh đi tham quan, kể cả các bạn trong nhóm X Thí dụ:
THAMQUAN.INP
Sau khi thực hiện chương trình ta sẽ thu được: ABCDEFH
Thí dụ trên cho chúng ta biết lớp học có 10 bạn học sinh mang tên là A B C D E F G H I vàJ Có 4 quan hệ giữa các nhóm như sau:
(B cóthể rủ được C)
(C vàE có thể rủ được A và F)
H > D (H cóthể rủ được D)
Trang 2AC > BDEH (A vàC có thể rủ được B, D, E và H)
Hai bạn X = AB đứng ra rủ các bạn trong lớp đi tham quan Vậy những aisẽ có mặt trong buổi tham quan
Bài giải
Hãy tưởng tượng vào buổi sáng hôm tham quan, đến giờ hẹn ta chỉ gặp haibạn A và B Hai bạn này dĩ nhiên sẽ bàn nhau rủ thêm người cùng đi Gọi X lànhóm bạn trẻ đứng ra rủ mọi người lúc đầu và gọi Y là nhóm bạn trẻ sẽ cùng nhaulên đường tham quan
Đầu tiên ta có Y := X
Vì B có thể rủ được C như mô tả trong quan hệ (1) nênlát sau C sẽ có mặt Ta có:
Y = X +[C] = [A,B,C]
Dấu cộng ở đây được hiểu là phép hội hai tập hợp Cácphần tử của một tập được liệt kê giữa hai dấu ngoặc vuông
Bây giờ trong nhóm đã có A và C do đó, theo quanhệ (4) hai bạn này sẽ rủ thêm được D, Evà H Ta có Y = [A,B,C,D,E,H] Lại theo quan hệ (2), hai bạn C và Esẽ đi rủ thêm được
F, do đó Y = [A,B,C,D,E,F,H] Đến đây ta thấycác bạn không còn rủ thêm được ai nữa Vậy nhóm đi tham quan sẽ là: Y =[A,B,C,D,E,H,F]
Để tăng tốc độ xử lý ta có nhận xét thêm sau đây: Mỗiquan hệ chỉ sử dụng tối đa một lần,
do đó ta sẽ đánh dấu quan hệ đã dùng rồi
Tổ chức dữ liệu Ta sẽ dùng kiểu tập hợp để biểu diễncác nhóm học sinh
Trước hết ta định nghĩ kiểu Ten gồm các tên học sinhtừ A đến Z
Type Ten = 'A' 'Z';
Tiếp theo ta định nghĩa kiểu nhóm là tập hợp các tên:
KieuNhom = set of Ten;
Sau đó ta định nghĩa kiểu mảng các quan hệ như là mộtmảng các tập Kiểu mảng này sẽ dùng để biểu diễn vế trái và vế phải của mỗiquan hệ
Type MangQuanHe = array[0 MN] ofKieuNhom;
Chương trình sử dụng các biến sau đây:
var f: text;
Trang 3lop: KieuNhom;
n: integer; { so hoc sinh }
m: integer; { so quan he }
trai,phai: MangQuanHe;
s: string;
x, y: KieuNhom;
dau: array[0 mn] of byte;
Tệp f dùng để quản lý dữ liệu vào (tệp THAMQUAN.INP).Biến lop dùng để chứa tên học sinh của lớp Sau khi biết giá trị n là số họcsinh, biến lop kiểu tập sẽ được khởi trị như sau: lop:=[ ];
for i:=0 to n-1 do
lop:=lop+[chr(ord('A')+i)];
Biến m chứa số lượng các quan hệ Hai mảng traivà phai chứa các tập ở mỗi vế trái và
phải tương ứng của mỗi quan hệ.Với thí dụ đã cho, sau khi đọc dữ liệu từ tệp
THAMQUAN.INP ta thu được
n=10, m=4,
trai[1]=[B], phai[1]=[C]
trai[2]=[C,E], phai[2]=[A,F]
trai[3]=[H], phai[3]=[D]
trai[4]=[A,C], phai[4]=[B,D,E,H]
Thủ tục Ru(x,y) cho biết nhóm x rủ được nhóm y khi đósẽ hoạt động như sau
procedure Ru(x: KieuNhom; var y:KieuNhom);
var truoc: KieuNhom;
i: integer;
begin
Trang 4for i:=1 to m do dau[i]:=0;
repeat
truoc:=y;
for i:=1 to m do
if dau[i] = 0 then
if (trai[i] <= y) then
begin
y:=y+phai[i];
dau[i]:=1;
end;
until y=truoc;
end;
Biến truoc dùng để lưu lại nhóm học sinh cómặt trước khi thực hiện một lần duyệt toàn bộ
các quan hệ để kết nạp thêm họcsinh Nếu sau một lần duyệt như vậy mà số học sinh trong nhóm không được tăngthêm, tức là y=truoc thì ta dừng thuật toán
Để đọc dữ liệu từ tệp THAMQUAN.INP vào các biến củachương trình ta dùng thủ tục Doc sau đây:
Procedure Doc;
var i: integer;
begin
assign(f,fn); {mo tep THAMQUAN.INP}
reset(f);
readln(f,n,m); {Doc cac gia tri n va m}
lop:=[ ]; {Lap danh sach lop gom n hoc sinh}
Trang 5for i:=0 to n-1 do
lop:=lop+[chr(ord('A')+i)];
for i:=1 to m do {Doc cac quan he}
begin
readln(f,s);
NapQuanHe(i);
end;
readln(f,s); {Doc dong chua nhom x: nhung nguoi dung ra ru nguoikhac}
StrToSet(s,x); {chuyen string s sang kieu tap x}
close(f);
end;
trong đó tên tệp fn được khai báo như một hằng:
fn = 'THAMQUAN.INP';
Thu tuc StrToset(s,x) chuyển xâu ký tự s sang dạngtập x như sau Đọc lần lượt từng ký tự s[i] của s Đó là tên học sinh Nếu tênnày có trong lớp thì đưa vào nhóm x Việc kiểm tra này chỉ cần khi nào trongxâu s có chứa các ký tự lạ như dấu cách chẳng hạn
Procedure StrToSet(s:string;var x:KieuNhom);
Var i:byte;
begin
x:= [ ];
for i:=1 to length(s) do
if (s[i] in lop) then
x:=x=[s[i]];
end;
Trang 6Thủ tục nạp quan hệ sẽ tìm trong dòng s đọc từ tệp f ký hiệu > rồi tách riêng vế trái và vế phải để lưu và các biến tương ứng
Procedure NapQuanHe(j:integer);
var i:byte;
begin
i:=pos('>',s);
StrToSet(copy(s,1,i),trai[j]);
StrToSet(copy(s,i+1,255),phai[j]);
end;
Để hiển thị dữ liệu kiểu tập x bạn hãy duỵet từng phần tử của tập nền, phần tử nào có trong
x ta in ra:
Procedure Xem(x:KieuNhom);
var c:Ten;
begin
for c:='A' to chr(ord('A')+ n-1) do
if (c in x) then write (c);
end;
Nguyễn Xuân Huy Các bài toán có yếu tố suy diễn
Nguyễn Xuân Huy
Phần 2
Số trước chúng ta đã tìm hiểu một thuật toán suy diễn từ tập X thu được tập Y bằng cách vận dụng các luật dạng L > R, trong đó L và R là các tập phần tử cho trước thể hiện quan
hệ các phần tử của L cùng phối hợp có thể kéo theo được các phần tử R Một dạng khác được gọi là bài toán quyết định có nội dung như sau: Hãy cho biết một tập đại diện K đủ
Trang 7nhỏ có thể kéo theo được toàn bộ các phần tử của tập nền ban đầu Trước hết chúng ta phát biểu lại bài toán trong số trước:
Bài toán (Ban cán sự): Một lớp học có n học sinh mang tên A, B, C Giữa các nhóm học
sinh có một số quan hệ tạm gọi là quan hệ ảnh hưởng, thí dụ, nếu ta viết AB < C thì có nghĩa là hai bạn A và B đồng thời cùng thuyết phục thì có thể yêu cầu bạn C tham gia một hoạt động nào đó cùng với mình Cho biết m quan hệ giữa các nhóm học sinh trong lớp Lớp dự định bầu một ban cán sự K thoả hai tính chất sau:
- a Ban cán sự phải có khả năng thuyết phục được cả lớp
- b Ban cán sự phải là một nhóm ít học sinh theo nghĩa sau: Nếu vắng một người trong ban cán sự thì ban không thể thuyết phục được cả lớp, tức là không thể đảm bảo được tính chất
a nữa Bạn hãy tìm một ban cán sự như vậy
Dữ liệu vào ghi trong tệp văn bản THAMQUAN.INP với cấu trúc như sau:
- Dòng đầu tiên: hai số tự nhiên n và m biểu thị số học sinh trong lớp và số các quan hệ, 2
≤ n ≤ 26, 1 ≤ m ≤ 50
- Tiếp theo là m dòng, mỗi dòng biểu thị một quan hệ dạng X > Y
Dữ liệu ra: Hiển thị trên màn hình danh sách một ban cán sự K
Thí dụ:
Sau khi thực hiện chương trình ta sẽ thu được:CEGIJ
Thí dụ trên cho chúng ta biết lớp học có 10 bạn học sinh mang tên là A, B, C, D, E, F, G,
H, I và J Có 4 quan hệ giữa các nhóm như sau:
(1) B > C (B có thể rủ được C)
(2) CE > AF (C và E có thể rủ được A và F)
(3) H > D (H có thể rủ được D)
(4) AC > BDEH (A và C có thể rủ được B, D, E và H)
Cần tìm một ban cán sự K của lớp thoả đồng thời hai điều kiện sau:
a) Ru(K) = Lop
b) Với mỗi học sinh h trong K ta phải có: Ru(K-[h]) <> Lop
Trong đó Ru(X) cho ta tập các học sinh mà nhóm X có thể rủ được (tính cả X), [h] là tập chứa một phàn tử H, K-[h] biểu thị hiệu của hai tập K và [h]
Bài giải: Trước hết chúng ta nhận xét rằng ban cán sự bao giờ cũng tồn tại, vì trong trường
hợp xấu nhất chúng ta có thể lấy cả lớp làm ban cán sự Nếu lấy cả lớp làm ban cán sự thì
có thể quá nhiều Để đảm bảo được điều kiện b ta hãy làm như sau: Lần lượt xét từng bạn học sinh h trong lớp: Nếu tạm bỏ bạn đó ra khỏi lớp mà số người còn lại vẫn rủ được cả lớp thì ta loại hẳn bạn đó Ngược lại, nếu thiếu bạn đó mà số còn lại không thể rủ được cả lớp thì ta phải mời bạn đó vào ban cán sự Thuật toán tìm ban cán sự K khi đó sẽ như sau:
Trang 8K := Lop;
for h:= hocsinhdau to hocsinhcuoi do
if Ru(K-[h]) = Lop then K := K - [h];
Bạn viết thêm thủ tục BanDaiDien và sửa thủ tục BaiLam trong số báo trước là hoàn tất chương trình:
procedure BanDaiDien(var k: kieunhom);
var hocsinhdau,hocsinhcuoi,h: Ten;
y: kieunhom;
begin
k := lop;
hocsinhdau:='A';
hocsinhcuoi:=chr(ord('A')+n-1);
for h:=hocsinhdau to hocsinhcuoi do
begin
Ru(k-[h],y);
if y=Lop then k:=k-[h];
end;
end;
procedure BaiLam;
var k: kieunhom;
begin
clrscr;
Doc;
writeln; writeln; writeln('Cac quan he: ');
XemQuanHe;
Ru(x,y);
writeln;
write('Ru(',s,') = '); Xem(y);
BanDaiDien(k);
writeln;
write('Ban dai dien = '); Xem(k);
readln;
end;
Với thí dụ đã cho, các bước tính toán sẽ như sau:
Bước 1: Khởi trị, với n=10 ta có Lop = "ABCDEFGHIJ", do đó ta khởi trị cho K := Lop,
tức là? K = "ABCDEFGHIJ"
Bước 2: Xét học sinh A ta thấy có thể loại A khỏi ban cán sự vì:
Ru("BCDEFGHIJ") = Lop.Vậy K= "BCDEFGHIJ"
Bước 3: Xét học sinh B ta thấy có thể loại B khỏi ban cán sự vì:
Ru("CDEFGHIJ") = Lop.Vậy K = "CDEFGHIJ"
Bước 4: Xét học sinh C ta thấy không thể loại C khỏi ban cán sự vì:
Ru("DEFGHIJ") = "DEFGHIJ" <> Lop
Vậy K = "CDEFGHIJ"
Từ bước 5 trở đi ta lần lượt xét nốt các học sinh của lớp và thu được kết quả như sau: Học sinh D: loại được, K = "CEFGHIJ"
Trang 9Học sinh E: không loại được, K = "CEFGHIJ".
Học sinh F: loại được, K = "CEGHIJ"
Học sinh G: không loại được,K = "CEGHIJ"
Học sinh H: loại được,K = "CEGIJ"
Học sinh I: không loại được,K = "CEGIJ"
Học sinh J: không loại được,K = "CEGIJ"
Kết quả cuối cùng: K = "CEGIJ"
Chú ý: Nếu trật tự duyệt các học sinh thay đổi ta có thể thu được ban cán sự khác.
Các bài toán có yếu tố suy diễn
Nguyễn Xuân Huy
Số trước chúng ta đã tìm hiểu một thuật toán suy diễn từ tập X để thu được tập Y bằng cách vận dụng các luật dạng L > R, trong đó L và R là các tập phần tử cho trước thể hiện quan hệ: các phần tử của L cùng phối hợp có thể kéo theo được các phần tử R Cài đặt bằng kiểu tập khá đơn giản Còn một cải tiến khác rất quan trọng vì nó giảm đáng kể độ phức tạp của thuật toán Cụ thể là theo thuật toán cải tiến ta có thể tính Ru(X) theo thời gian n*m, trong đó n là số học sinh của lớp, m là số quan hệ giữa các nhóm học sinh Nhắc lại rằng, thuật toán Ru ở dạng ban đầu đòi hỏi thời gian n*n*m Vì sao vậy? Ta giả thử rằng để tính Ru(X), mỗi lần duyệt m quan hệ ta chỉ thêm được có 1 bạn học sinh Như vậy
ta cần duyệt các quan hệ n*m lần Mỗi lần duyệt quan hệ ta lại phải tính toán trên các tập chứa n phần tử Vậy thời gian tổng cộng sẽ là n*n*m Để tìm ban đại diện ta phải gọi n lần thuật toán Ru do đó nếu cải tiến thuật toán Ru ta sẽ được lợi khá nhiều Bài này sẽ trình bày thuật toán Ru theo phương án cải tiến Trước hết chúng ta nhắc lại đầu bài đã đăng trong số báo trước:
Bài toán: (Ban cán sự) Một lớp học có n học sinh mang tên A, B, C Giữa các nhóm học
sinh có một số quan hệ tạm gọi là quan hệ ảnh hưởng, thí dụ, nếu ta viết AB > C thì có nghĩa là hai bạn A và B đồng thời cùng thuyết phục thì có thể yêu cầu bạn C tham gia một hoạt động nào đó cùng với mình Cho biết m quan hệ giữa các nhóm học sinh trong lớp Lớp dự định bầu một ban cán sự K thoả hai tính chất sau:
a Ban cán sự phải có khả năng thuyết phục được cả lớp
b Ban cán sự phải là một nhóm ít học sinh theo nghĩa sau: Nếu vắng một người trong ban cán sự thì ban không thể thuyết phục được cả lớp, tức là không thể đảm bảo được tính chất
a nữa
Bạn hãy tìm một ban cán sự như vậy
Dữ liệu vào ghi trong tệp văn bản THAMQUAN.INP với cấu trúc như sau:
Trang 10· Dòng đầu tiên: hai số tự nhiên n và m biểu thị số học sinh trong lớp và số các quan hệ, 2
<= n <= 26, 1 <= m <= 100
· Tiếp theo là m dòng, mỗi dòng biểu thị một quan hệ dạng X > Y Dữ liệu ra: Hiển thị trên màn hình danh sách một ban cán sự K
Dữ liệu ra: Hiển thị trên màn hình danh sách một ban cán sự K
Thí dụ:
Sau khi thực hiện chương trình ta sẽ thu được: CEGIJ
Thí dụ trên cho chúng ta biết lớp học có 10 bạn học sinh mang tên là A, B, C, D, E, F, G,
H, I và J Có 4 quan hệ giữa các nhóm như sau:
(1) B > C (B có thể rủ được C)
(2) CE > AF ( C và E có thể rủ được A và F)
(3) H > D (H có thể rủ được D)
(4) AC > BDEH (A và C có thể rủ được B, D, E và H)
Cần tìm một ban cán sự K của lớp thoả đồng thời hai điều kiện sau:
a) Ru(K) = Lop
b) Với mỗi học sinh h trong K ta phải có: Ru(K-[h]) <> Lop.
Trong đó, Ru(X) cho ta tập các học sinh mà nhóm X có thể rủ được (tính cả X), [h] là tập chứa một phần tử h, K-[h] biểu thị hiệu của hai tập K và [h]
Ta đã biết cách tìm ban đại diện như sau:
procedure BanDaiDien(var k: kieunhom);
var hocsinhdau,hocsinhcuoi,h: Ten;
y: kieunhom;
Begin
k := lop;
Trang 11hocsinhcuoi:=chr(ord('A')+n-1);
for h:=hocsinhdau to hocsinhcuoi do
begin
Ru(k-[h],y);
if y=Lop then k:=k-[h];
end;
End;
Bây giờ chúng ta cải tiến thủ tục Ru Muốn biết khi nào vế trái của quan hệ thứ i nằm trong tập Ru y ta dùng con đếm NTrai[i] Lúc đầu ta khởi trị NTrai[i] bằng số phần tử có mặt trong vế trái của quan hệ thứ i Với thí dụ đã cho ở đầu bài ta tính được bảng sau:
Ntrai[i] cho biết vế trái của quan hệ thứ 4 gồm có bao nhiêu học sinh Nói cách khác, để một nhóm học sinh Y nào đó chứa trọn vế trái của quan hệ thứ i thì nhóm đó phải chứa đủ Ntrai[i] học sinh của vế trái này Ngoài ra với mỗi học sinh ta phải biết học sinh đó có mặt trong vế trái của những quan hệ nào Ta dùng một mảng hai chiều a để lưu trữ thông tin này:
Để tiện tính toán, trong thủ tục Ru cải tiến ta biểu diễn danh sách các học sinh trong mỗi nhóm dưới dạng string Giả sử ta cần tính Y := Ru(X) với X = 'AB’ Thoạt tiên ta khởi trị
Y := X, tức là đặt Y = ‘AB’ Sau đó ta xét lần lượt các phần tử của Y
Phần tử đầu tiên của Y là A Vì A có mặt trong quan hệ 4 nên ta giảm NTrai[4] đi 1 đơn vị,
ta có: Ntrai[4]=2-1=1 Lúc này Ntrai[4]=1 cho ta biết còn thiếu 1 học sinh nữa thì Y sẽ chứa trọn vế trái của quan hệ 4
Trang 12Tiếp theo ta xét phần tử B của Y B nằm trong vế trái của quan hệ 1 Ta giảm Ntrai[1] đi 1 đơn vị, Ntrai[1] = 1-1 = 0 Điều này cho biết vế trái của quan hệ 1 đã nằm trọn trong Y, do
đó vế trái thứ nhất này sẽ rủ thêm được vế phải Ta thêm phai[1] vào Y và thu được:
Y = ‘AB’ @ ‘C’ = ‘ABC’ Ta tạm ký hiệu @ là phép toán thêm những học sinh mới vào danh sách đã biết
Bây giờ lại xét tiếp phần tử C trong Y C có mặt trong các vế trái của 2 quan hệ, thứ 2 và thứ 4 Ta có:
Ntrai[2] = 2 -1 = 1,
Ntrai[4] = 1 - 1 = 0, do đó Y = ‘ABC’@phai[4]=’ABC’@’BDEH’=’ABCDEH’
Tiếp theo ta xét phần tử D Vì D không xuất hiện trong vế trái nào nên ta bỏ qua
Tiếp theo là phần tử E Ta có, Ntrai[2] = 1-1 = 0, do đó:
Y = ‘ABCDEH’@phai[2]=’ABCDEH’@’AF’=’ABCDEHF’
Với H ta có Ntrai[3]=1-1=0, do đó
Y = ‘ABCDEHF’@phai[3]=’ABCDEHF’@’D’=’ABCDEHF’
Vì F không thuộc vế trái nào cho nên ta bỏ qua
Danh sách Y đã được duyệt xong Ta có kết quả Y = Ru(‘AB’) = ‘ABCDEHF’
Hàm Ru khi đó sẽ như sau Ta dùng kiểu xâu dài tối đa 26 ký tự để biểu diễn các nhóm học sinh Kiểu Ten cho biết các tên học sinh Biến mảng d[t] cho biết học sinh tên t có mặt trong vế trái của bao nhiêu quan hệ Các kiểu dữ liệu và biến tổng thể được khai báo như sau: