1. Trang chủ
  2. » Công Nghệ Thông Tin

Thuật toán Heuristic

10 2,3K 40
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Tìm Hiểu Thuật Toán Heuristic
Tác giả Nguyễn Văn Sơn
Trường học Trường Đại Học Công Nghệ Thông Tin
Chuyên ngành Công Nghệ Thông Tin
Thể loại bài viết
Định dạng
Số trang 10
Dung lượng 92 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Thuật toán Heuristic

Trang 1

Tìm hiểu thuật toán Heuristic

Nguyễn Văn Sơn

Đối với nhiều bài toán, hoặc không có lời giải, hoặc độ phức tạp tính toán là hàm mũ, hoặc

là bài toán NP-đầy đủ…, có nghĩa là nó không có lời giải khả thi, thì thông thường thay vì tìm lời giải tối ưu cho chúng, chúng ta cố gắng tìm lời giải có thể chấp nhận được, đáp ứng được yêu cầu của thực tế Các lời giải này chính là các thuật toán heuristic

Các thuật toán tìm kiếm luôn luôn đóng vai trò quan trọng trong việc giải các bài toán tin học Các thuật toán loại này rất phong phú, có thể kể đến như: vét cạn, đệ quy quay lui, nhánh cận, nhị phân…Tuy nhiên, khi gặp những bài toán có không gian tìm kiếm lớn (đặc biệt trong các trò chơi cờ) thì các thuật toán tìm kiếm thông thường không cho kết quả hoặc kết quả không tối ưu (do những hạn chế về thời gian và bộ nhớ) Một hướng tiếp cận độc đáo có thể đáp ứng được đòi hỏi cho nhiều bài toán loại này là dùng thuật toán

Heuristic

Thuật ngữ Heuristic xuất phát từ tiếng Hy Lạp là ″heuriskein″ có nghĩa là ″tìm kiếm″ hoặc

″phát minh″ Chắc chắn chúng ta vẫn còn nhớ câu chuyện về nhà bác học Archimedes Khi phát hiện ra định luật về trọng lượng riêng, ông đã trần truồng chạy ra đường và kêu lớn

″tôi tìm ra rồi″ Thực ra, lúc đó ông đã kêu lên ″heureka″, về sau này người ta đổi từ này thành ″eureka″

Thuật ngữ Heuristic được Feigenbaum Feldman định nghĩa như sau: ″Heuristic là các quy tắc, phương pháp, chiến lược, mẹo giải hay phương cách nào đó nhằm làm giảm khối lượng tìm kiếm lời giải trong không gian bài toán cực lớn″

Tư tưởng chính để giảm khối lượng tìm kiếm là thay vì ″loại bỏ các hướng tìm kiếm chắc chắn không dẫn đến lời giải″, ta hãy ″chọn đi theo hướng có nhiều khả năng dẫn đến lời

giải″

Do thuật toán Heuristic được con người sử dụng thường mang đặc trưng của những gợi ý hay lời khuyên, nên các phương pháp dựa trên Heuristic đôi khi không chỉ ra con đường trực tiếp để đạt tới mục đích

Nhiều kết quả nghiên cứu trong trí tuệ nhân tạo cho thấy rằng, tuy có nhiều điểm mạnh nổi bật, nhưng trong một vài lĩnh vực nghiên cứu nào đó thì các phương pháp Heuristic còn

bộc lộ những điểm yếu nhất định Điều phức tạp chính là vì mọi chương trình máy tính

phải đảm bảo chắc chắn kết thúc công việc (theo định nghĩa một thuật toán phải đảm bảo tính đúng và tính dừng) Vì vậy, nếu nói rằng một chương trình nào đó sử dụng Heuristic thì kết luận về tính dừng chỉ đúng trong đa số các trường hợp Do đó, trong phần lớn trường hợp giải quyết bài toán, các chương trình Heuristic có lúc cho kết quả mong đợi, đôi khi lại không

Các Heuristic không chỉ tác động đến các chiến lược tìm kiếm, mà còn ảnh hưởng quyết

định tới các chiến lược điều khiển (hướng tìm kiếm trong không gian bài toán và xử lý

cạnh tranh) Đối với những bài toán trí tuệ phức tạp, số khả năng có thể lớn tới mức không thể có một máy tính nào dầu hiện đại đến mấy đáp ứng nổi Do vậy, thủ tục duyệt toàn thể không thể chấp nhận được Trong phần lớn các bài toán chứng minh định lý sử dụng logic,

số khả năng cần phải xét trở lên vô hạn Việc lựa chọn một nước đi tốt nhất trong trò chơi đòi hỏi phải tìm kiếm trong khoảng 1040 khả năng khác nhau, thậm chí đối với chơi cờ, số

Trang 2

khả năng cỡ 10120 Một cách xử lý tốt trong những trường hợp này là sử dụng thao tác rút gọn các hướng tìm kiếm

Vấn đề quan trọng là ở chỗ, chúng ta biết khai thác khéo léo thông tin tại mỗi trạng thái để tìm ra thứ tự ưu tiên và đẩy nhanh quá trình tìm kiếm Thông thường ta gắn với mỗi trạng

thái của bài toán với một số đo (một hàm đánh giá) nào đó để đánh giá mức độ gần đích

của nó

Một kỹ thuật Heuristic được coi là hợp lý khi nó cho phép tiến hành đánh giá các khả năng để làm rõ khả năng nào tốt hơn các khả năng còn lại Những ví dụ điển hình về các

hàm đánh giá là các ước lượng khoảng cách đường chim bay từ một đỉnh nào tới đỉnh đỉnh đích trong bài toán xác định đường đi ngắn nhất, hay các đánh giá ước lượng mức độ quan trọng của các quân cờ trong mỗi thế cờ dựa trên tổ hợp các trọng số của chúng…

Để minh hoạ cho thuật toán Heuristic, chúng ta cùng nghiên cứu bài toán sau đây: bài toán

8-puzzle (đây là một trò chơi được một nhà thiết kế trò chơi nổi tiếng của Mỹ là Sam Loyd

phát minh vào cuối những năm 1870; nó đã trở thành một trò chơi được cực kỳ được ưa chuộng ở Mỹ vào thời điểm đó)

Bài toán:

Có 8 số mang các giá trị từ 1 tới 8 được sắp xếp vào một bảng các ô vuông kích thước 3x3 Mỗi số đó được xếp vào một ô, có một ô của bảng bỏ trống Cho trước hai bảng các con số (thể hiện cho trạng thái nguồn và trạng thái đích của bài toán), hãy chỉ ra một dãy các phép chuyển các con số (nếu có) để thu được một một bảng (trạng thái đích) từ bảng còn lại (trạng thái nguồn) Bạn chỉ được phép chuyển các con số lên trên, xuống dưới, sang trái và sang phải từ một ô có con số sang ô trống (bài toán này còn có dạng phức tạp hơn là 15-puzzle)

Rõ ràng, đối với bài toán này nếu dùng phương pháp duyệt toàn bộ thì không hợp lý Để

giảm không gian tìm kiếm, ta xây dựng một thứ tự ưu tiên để duyệt các hướng đi Do đó,

khi duyệt thứ tự ưu tiên theo thứ tự giảm dần của khả năng dẫn đến lời giải, ta sẽ có cơ hội tiếp cận đến lời giải nhanh hơn là duyệt một cách mù quáng!

Tuy nhiên, điểm mấu chốt là: làm thế nào để đánh giá khả năng dẫn đến lời giải của một hướng đi? Nếu đánh giá này chính xác, chúng ta sẽ tìm thấy lời giải nhanh hơn còn nếu không thì trong trường hợp xấu nhất, lại trở về vét cạn toàn bộ

Trong bài toán này, ta sử dụng hàm đánh giá ký hiệu là h với ý nghĩa: h(u) cho biết số các chữ số trong trạng thái u không trùng với vị trí của nó trong trạng thái đích Khi đó, trạng thái có tiềm năng dẫn tới đích nhanh nhất là trạng thái có hàm đánh giá h đạt giá trị min

Thuật toán cho trò chơi 8-puzzle:

Một số ký hiệu

- Tập P các trạng thái chờ quyết định được tổ chức dưới dạng stack

- Tập Q các trạng thái đã phát triển được tổ chức dưới dạng hàng đợi

- Tập P′ lưu trữ tạm thời các trạng thái kề v của u khi ta phát triển một đỉnh u (v thu được

từ u thông qua một phép di chuyển con số)

- Biến found

Trang 3

- Hàm father.

Thuật toán:

Input: trạng thái ban đầu u0 và trạng thái đích ut

1.P← { u0 } ; Q ← Φ ; found ← false; P′ ← Φ ;

2.While(P ≠ Φ ) and (not found) do

2.1 Loại trạng thái u ở đỉnh stack P và đặt nó vào Q:

Pop(P,u);

Ađ(u,Q);

2.2 If u=ut then found ← true

Else for v thuộc kề(u) do

If v không thuộc P hợp Q then

Begin

father (v) ← u;

Ađ (v,P′);

End;

If P′ ≠ Φ then

Begin

Sắp xếp P′ theo thứ tự tăng của hàm h Chuyển P′ vào đỉnh stack P sao cho trạng thái nhiều hứa hẹn nhất (có giá trị hàm h nhỏ nhất) ở đỉnh của P

End;

(Chú ý: Sau khi chuyển P′ vào đỉnh stack P thì P′ trở thành rỗng.)

Output: Nếu found = false thì bài toán vô nghiệm.

Nếu found = true thì nghiệm là đường đi từ u0 tới ut được xác định bằng cách sử dụng hàm father

Cây tìm kiếm được hình thành do sử dụng thuật toán Heuristic ở trên được minh hoạ như trong hình vẽ dưới (nét đậm thể hướng tìm kiếm), số ghi cạnh các đỉnh là giá trị của hàm h tại đỉnh đó

Trang 4

Minh hoạ cây tìm kiếm cho trò chơi 8-puzzle bằng thuật toán Heuristic

Chương trình minh hoạ cho thuật toán Heuristic giải quyết bài toán ở dạng tổng quát được viết bằng ngôn ngữ Pascal như dưới đây

Dữ liệu vào cho trong file SO.INP: dòng đầu là một số n (1<N2-1)-puzzle) Tiếp theo là hai nhóm dòng, mỗi nhóm gồm n dòng (gồm các số được ghi cách nhau một dấu cách) lần lượt minh hoạ cho bảng số nguồn và bảng số đích Dữ liệu ra được ghi vào file SO.OUT gồm nhiều nhóm dòng, mỗi nhóm gồm n+1 dòng: bắt đầu là một số chỉ thứ tự của bảng số được phát triển tính từ bảng số nguồn và n dòng tiếp theo minh hoạ cho bảng số đó Nếu không tồn tại lời giải thì ghi một số 0

Ví dụ:

SO.INP

3

2 6 3

1 6 4

7 0 5

1 2 3

8 0 4

7 6 5

SO.OUT

1

2 8 3

1 4

7 6 5

2

2 3

1 8 4

7 6 5

Trang 5

2 3

1 8 4

7 6 5

4

1 2 3

8 4

7 6 5

5

1 2 3

8 4

6 5

Sau đây là toàn văn chương trình:

PROGRAM heuristic;

{$B-}{$M 65000,0,655360}

Uses Crt;

Const Max=6;

fi=′SO.INP′;

fo=′SO.OUT′;

Type Vec=Array[1 Max,1 Max] of byte; Item=record Ma:vec;Father,child:longint; End; Pointer =^node; Node=record Infor:item; Next:pointer; End;

Node1=array[1 4] of vec;Tp=0 10;

Var

U :item; Id :longint;

Front,rear,top:pointer; P :node1;

Dau,dich :vec; Found :boolean;

N :2 10; So_pts :tp;

I,j :tp;

ff:text;

PROCEDURE Vi_tri(a:vec;var k,t:TP);

Var i,j:1 max;

Begin For i:=1 to n do For J:=1 to n do

If a[i,j]=0 then

Begin K:=i; T:=j; Exit; End;

End;

{minh hoa cho cac phep di chuyen so}

PROCEDURE Left(a:vec;var lef:vec;i,j:tp); Begin A[i,j]:=A[i,j+1];A[i,j+1]:=0; Lef:=A; End;

PROCEDURE Right(a:vec;var righ:vec;i,j:tp); Begin A[i,j]:=A[i,j-1]; A[i,j-1]:=0; Righ:=A; End;

PROCEDURE Up(a:vec;var u:vec;i,j:tp); Begin A[i,j]:=A[i+1,j]; A[i+1,j]:=0; U:=A;

Trang 6

PROCEDURE Down(a:vec;var dow:vec;i,j:tp);

Begin A[i,j]:=A[i-1,j];A[i-1,j]:=0;Dow:=A

End;

PROCEDURE Pop(var Top:pointer;var U:Item);

Var Q:Pointer;

Begin Q:=Top;Top:=Top^.next;U:=Q^.infor; Dispose(q) End;

PROCEDURE Ađ(u:Item;var rear,front:pointer);

Var Q:pointer;

Begin New(q); Q^.infor:=u;

Q^.next:=nil;

If front =nil then front:=q

Else rear^.next:=q;Rear:=q

End;

FUNCTION Count(a:vec):byte;

Var i,j :0 10; Dem :byte;

Begin Dem:=0; For i:=1 to n do For j:=1 to n do

If a[i,j]<>Dich[i,j] then dem:= dem+1;Count:=Dem End;

FUNCTION Dung(a,b:vec):boolean;

Var i,j:tp;

Begin Dung:=false;

For i:=1 to n do For J:=1 to n do

If a[i,j]<>b[i,j] then exit;Dung:=true;

End;

FUNCTION KtrăFront ,top:pointer;a:vec):boolean; Var q :Pointer; Ok :boolean;

Begin Ok:=true; Q:=top;

While (q<>nil) and ok do

if Dung(Q^.infor.ma,A) then ok:=False

Else Q:=q^.next; Q:=Front;

While (q<>nil) and ok do

if Dung(Q^.infor.ma,a) then ok:=False

Else Q:=q^.next; Ktra:=ok

End;

PROCEDURE Nhap;

Var i,j:1 max;

Begin assign(ff,fi);

reset(ff);

readln(ff,n);

For i:=1 to n do

For j:=1 to n do

Read(ff,dau[i,j]);

For i:=1 to n do

For j:=1 to n do

Trang 7

close(ff)

End;

PROCEDURE In_vec(a:vec);

Var i,j:byte;

Begin For i:= 1 to n do

Begin For j:=1 to n do

If a[i,j]<>0 then write(ff,a[i,j]:3) else write(ff,' ');

writeln(ff);

End;

End;

FUNCTION Nhap_cx(a:vec):Boolean;

Var i,j :byte; S1,s2 :Set of byte;

Begin S1:=[];s2:=[];

For I:=0 to N*N-1 do s1:=s1+[i];

Nhap_cx:=False; For i:=1 to n do

For J:=1 to n do

If not(a[i,j] in s1)or (a[i,j] in s2)then exit

Else S2:=s2+[a[i,j]];

Nhap_cx:=true;

End;

PROCEDURE Init;

Var Uo:pointer;

Begin Clrscr;

Nhap;

If not Nhap_cx(dau)or not Nhap_cx(dich) then

begin Writeln('LOI KHI DOC DU LIEU');

readln;

halt;

end;

Found:=false;New(Uo);

Uô.infor.ma:=Dau;Uô.infor.father:=0;

Uô.infor.child:=1;Uô.next:=nil;

Top:=Uo;front:=nil;Rear:=nil;

End;

PROCEDURE Ptu_ke(var p:node1;U:vec;i,j:tp;var so_pts:tp); Var v :vec;

Begin If I>1 then Begin Down(u,v,i,j);

If ktrăfront,top,v) then

Begin So_pts:=so_pts+1; P[so_pts]:=v;End

End;

If j>1 then

Begin Right(u,v,i,j);

If ktrăfront,top,v) then

Begin So_pts:=so_pts+1;P[so_pts]:=v End

End;

Trang 8

If j

If ktrăfront,top,v) then

Begin So_pts:=so_pts+1; P[so_pts]:=v; End

End;

If I

If ktrăfront,top,v) then

Begin So_pts:=so_pts+1;P[so_pts]:=v;End

End;

End;

PROCEDURE Sxep(Var P:node1;so_pts:tp);

Var Tg :vec; T,i,j,min :tp; B :array[1 4] of byte;

Begin For i:=1 to so_pts do B[i]:=count(p[i]);

For i:=1 to so_pts-1 do

Begin Min:=i;

For j:=i+1 to so_pts do

If b[j] If min>i then

Begin T:=b[i]; B[i]:=b[min];B[min]:=t;

Tg:=p[i];P[i]:=p[min];P[min]:=tg; End

End

End;

PROCEDURE Push(var top:pointer;p:node1;child:longint;so_pts:tp); Var i:tp;v:pointer;

Begin For i:=so_pts downto 1 do Begin

New(v); V^.infor.ma:=p[i];

V^.infor.father:=child; Id:=id+1;

V^.infor.child:=id;

V^.next:=top; Top:=v;End

End;

PROCEDURE In_Kq;

Var p :pointer;i,buoc :longint;

Begin Buoc:=0;

P:=front;I:=1;

assign(ff,fo);

rewrite(ff);

if not found then

begin

write(ff,0);

close(ff);

exit;

end;

P:=p^.next;

While P<>nil do

Begin If p^.infor.father=i then

Begin

I:=p^.infor.child; Buoc:=buoc+1;

Writeln(ff,buoc);In_vec(P^.infor.ma);

Trang 9

End; P:=p^.next

End;

close(ff);

End;

Begin

Clrscr;Init;

While (top<>nil) and not(Found) do

Begin Pop(Top,U); Ađ(u,Rear,Front);

If dung(u.ma,dich) then found:=true

Else Begin Vi_tri(U.ma,i,j); So_pts:=0;

Ptu_ke(p,u.ma,i,j,so_pts);

sxep(p,so_pts);Push(top,p,u.child,so_pts) End

End;

In_kq;

End

Chú ý: Việc lựa chọn hàm đánh giá cho bài toán trên có thể tính thông qua tổng khoảng

cách ngắn nhất (tính theo ô) của từng con số trong trạng thái hiện tại so với vị trí đúng của

nó trong trạng thái đích

Một ví dụ khác là bài toán tô màu cho đồ thị Giả sử G = là một đồ thị không định hướng

Yêu cầu tô màu cho tất cả các đỉnh của G sao cho hai đỉnh được nối bằng một cung thì phải có hai màu khác nhau Có thể thấy rằng bài toán tô màu này sao cho số màu được dùng là ít nhất là một bài toán NP-đầy đủ Lúc này, ta tìm một lời giải tốt có thể chấp nhận được theo một thuật toán heuristic như sau:

Ban đầu chọn một màu và một đỉnh xuất phát Ta tô màu đỉnh này và tất cả các đỉnh khác

có thể tô được mà vẫn thoả mãn điều kiện của bài toán Chúng ta chọn màu mới và một đỉnh xuất phát mới (chưa được tô), ta tô đỉnh này và tất cả các đỉnh khác (còn chưa được tô) có thể tô được bằng màu thứ hai, và cứ như vậy…cho đến khi tô hết các đỉnh của G thì thôi

Bài tập 1: Các ô vuông thần bí (đề thi Olympic tin học quốc tế 1996)

Kế tục thành công của trò chơi với khối lập phương thần bí, Ngài Rubik sáng tạo ra dạng phẳng của trò chơi này gọi là trò chơi các ô vuông thần bí Đây là một bảng gồm 8 ô vuông bằng nhau (xem Hình 1)

Chúng ta xét bảng trong đó mỗi ô vuông có một màu khác nhau Các màu được ký hiệu bởi tám số nguyên dương đầu tiên (xem Hình 1) Trạng thái của bảng được cho bởi dãy ký hiệu màu của các ô được viết lần lượt theo chiều kim đồng hồ bắt đầu bởi ô ở góc trái trên

và kết thúc tại ô ở góc trái dưới Ví dụ, trạng thái của bảng trong hình 1 được cho bởi dãy (1, 2, 3, 4, 5, 6, 7, 8) Trạng thái này được gọi là trạng thái khởi đầu (hay trạng thái đích)

Có thể dùng 3 phép biến đổi cơ bản đối với bảng có tên là′A′, ′B′, ′C′:

′A′: đổi chỗ dòng trên và dòng dưới Ví dụ sau phép biến đổi ′A′thì hình 1 thành:

Trang 10

′B′: thực hiện một phép hoán vị vòng quanh sang phải Ví dụ sau phép biến đổi ′B′ thì hình

1 thành:

′C′: quay theo chiều kim đồng hồ bốn ô giữa Ví dụ sau phép biến đổi ′C′ thì hình 1 thành:

Biết rằng từ một trạng thái khởi đầu luôn có thể chuyển về một trạng thái bất kỳ bằng cách dùng các phép biến đổi cơ bản nói trên

Hãy viết chương trình tìm các phép biến đổi cơ bản để chuyển bảng từ trạng thái khởi đầu cho trong hình 1 về một trong các trạng thái cho trước (Câu A), bạn sẽ được thêm hai điểm nếu số lượng phép biến đổi tìm được không vượt quá 300 (Câu B)

Dữ liệu vào: file INPUT.TXT chứa 8 số nguyên dương trong dòng đầu tiên mô tả trạng

thái đích

Dữ liệu ra: trong dòng đầu tiên của file OUTPUT.TXT chứa một số L là số lượng phép

biến đổi của dãy các phép biến đổi tìm được Trong L dòng tiếp theo phải ghi dãy tên các phép biến đổi cơ bản theo trình tự thực hiện, mỗi tên ghi ở vị trí đầu tiên của mỗi dòng

Ví dụ về dữ liệu vào và dữ liệu ra:

Bài tập 2: (Bài toán người bán hàng)

Người bán hàng có hành trình sao cho mỗi thành phố đi đến đúng một lần và quay trở lại thành phố xuất phát Hãy tìm một hành trình đi ngắn nhất cho người bán hàng đó

Thuật toán chúng ta vừa nghiên cứu ở trên đã chứng tỏ sự hiệu quả của nó, bởi lẽ thực tiễn ngày nay đã chỉ ra rằng đi đôi với sự phát triển của khoa học và công nghệ thì chúng ta ngày càng gặp nhiều bài toán mà đối với chúng rất khó xác định có tồn tại hay không một lời giải chính xác Sử dụng thuật toán này cùng với một vài kỹ năng lập trình, bạn đọc có thể dễ dàng viết một vài chương trình trò chơi đơn giản

Ngày đăng: 11/09/2012, 15:00

TỪ KHÓA LIÊN QUAN

w