Phương pháp thử-sai hoặc Heuristic, nói chung đều dựa trên một điểm cơ bản và dựa trên trí thông minh của chính con người để giải bài toán, máy tính chỉ đóng vai trò thực thi mà thôi. Còn các phương pháp trí tuệ nhân tạo dựa trên trí thông minh của máy tính. Trong những phương pháp này, người ta sẽ đưa vào máy tính thông minh nhân tạo giúp máy tính bắt chước một phần khả năng suy luận như con người. Từ đó, khi gặp một vấn đề, máy tính sẽ dựa trên những điều đó đã được “học” để tự đưa ra phương án giải quyết vấn đề.
CHƯƠNG 3
LÝ THIẾT TRÒ CHƠI 8 SỐ 3.1. Tìm hiểu trò chơi 8 số
3.1.1. Mục đích giải quyết bài toán 8 số trên máy tính
Như ta đã biết bài toán 8 số là bài toán phổ biến được nhiều người biết đến, đặc biệt là những người thuộc ngành tin học. Bài toán tuy đơn giản nhưng đỏi hỏi người giải phải tư duy. Nếu chúng ta di chuyển từng bước bằng tay cho từng con số từ trạng thái bắt đầu đến trạng thái về đích đòi hỏi con người phải tốn một khoảng thời gian, còn nhanh hay chậm còn tùy thuộc vào trí tuệ và độ nhanh nhẹn của mỗi người. Dựa vào thuật giải A* và giải thuật Dijsktra để cài đặt vào máy tính. Lúc này máy tính thay thế con người giải quyết vấn đề là nhập vào trạng thái ban đầu và cho ra trạng thái đích giải bài toán một cách nhanh chóng.
Ví dụ trò chơi: Chúng ta có bảng 3x3 ô và tám quân mang số hiệu từ 1 đến 8 được xếp vào tám ô, còn lại một ô trống, chẳng hạn như trong hình 3.1 bên trái. Trong trò chơi này, bạn có thể chuyển dịch các quân ở cạnh ô trống tới ô trống đó. Vấn đề của bạn là tìm ra một dãy các chuyển dịch để biến đổi cảnh huống ban đầu (hình 3.1 bên trái) thành một cảnh huống xác định nào đó, chẳng hạn cảnh huống trong hình 3.1 bên phải.
Hình 3.1 Trạng thái ban đầu và trạng thái kết thúc của bài toán số
Trong bài toán này, trạng thái ban đầu là ở bên trái hình 3.1, còn trạng thái kết thúc ở bên phải hình 3.1.
Tương ứng với các quy tắc chuyển dịch các quân, ta có bốn toán tử: up (đẩy quân lên trên), down (đẩy quân xuống dưới), left (đẩy quân sang trái),
right (đẩy quân sang phải). Rõ ràng là, các toán tử này chỉ là các toán tử bộ phận; chẳng hạn, từ trạng thái ban đầu (hình 3.1 bên trái), ta chỉ có thể áp dụng các toán tử down, left, right.
Cụ thể ta có thể cài đặt mỗi bảng 3x3 bằng một ma trận aij vuông cấp 3, trong đó aij {0, 1, 2, 3, 4, 5, 6, 7, 8} và aij ≠ akl khi i ≠ k hoặc j ≠ l.
Toán tử chuyển trạng thái xác định như sau ai j0 0 0:
0 0 ij 0 0 0 0 up ij i 1j 0 0 0 0 0 0 a nên j j i i i i 1 i 1 f a a nên i i j j i 1 0 nên i i j j i 1 0 0 ij 0 0 0 0 down ij i 1 j 0 0 0 0 0 0 a nên j j i i i i 1 i 3 f a a nên i i j j i 3 0 nên i i j j i 3 0 0 ij 0 0 0 0 left ij i j 1 0 0 0 0 0 0 a nên i i j j j j 1 j 1 f a a nên i i j j j 1 0 nên i i j j j 1 0 0 ij 0 0 0 0 right ij i j 1 0 0 0 0 0 0 a nên i i j j j j 1 j 3 f a a nên i i j j j 3 0 nên i i j j j 3
Trong các ví dụ trên việc tìm ra một biểu diễn thích hợp để mô tả các trạng thái của vấn đề là khá dễ dàng và tự nhiên. Song trong nhiều vấn đề việc tìm hiểu được biểu diễn thích hợp cho các trạng thái của vấn đề là hoàn toàn không đơn giản. Việc tìm ra dạng biểu diễn tốt cho các trạng thái đóng vai trò hết sức quan trọng trong quá trình giải quyết một vấn đề. Có thể nói rằng, nếu
ta tìm được dạng biểu diễn tốt cho các trạng thái của vấn đề, thì vấn đề hầu như đã được giải quyết.
3.1.2. Mô tả
Một bảng 3x3 với các ô trong đó có số từ 18 và 1 ô trống, các ô được đặt ở các vị trí ngẫu nhiên, ô trống và ô số có thể đổi chỗ cho nhau, tìm cách di chuyển các ô sao cho các con số về đúng thứ tự, bài toán đặt ra ở đây là tìm phương án tối ưu sao cho số lần di chuyển là ít nhất.
Trạng thái ban đầu
Trạng thái đích
Trạng thái đích có thể có 2 trường hợp có thể xảy ra:
và
Với mỗi trạng thái ban đầu, chỉ tìm được 1 trạng thái đích có thể đạt tới. Điều đầu tiên cần phải quan tâm để giải bài toán này là xác định trạng thái đích. Trạng thái đích được xác định dựa trên trạng thái ban đầu.
3.1.3. Xác định trạng thái đích
Đầu tiên hãy thử tính có bao nhiêu số bé hơn 8 ở sau ô chứa giá trị 8. Kết quả nhận được là 6 (những ô màu vàng)
Làm tương tự như vậy với ô có giá trị 6. Dễ thấy trong 3 ô (4,7,5) có 2 giá trị nhỏ 6 là 4,5.
Làm như trên từ ô đầu tiên (2) tới ô cuối cùng (5) và cộng dồn các giá trị nhận được:
N = 1+6+1+0+2+0+1+0=11
Nếu N là số lẻ thì chúng ta chỉ có thể có đáp án là trạng thái A, ngược lại là trạng thái B.
Trạng thái A
Trạng thái B
Chúng ta đã xác định được trạng thái đích cần đạt được, bây giờ chúng ta bắt đầu tìm kiếm giải thuật để tìm ra đích.
Trên thực tế có nhiều giải thuật để tìm ra đích, ở đây tôi chỉ áp dụng thuật toán A*.
3.2. Thuật toán tìm đáp án
3.2.1. Giới thiệu về A*
A* là một thuật toán Heuristic dựa trên thuật toán Dijsktra. Thế nên phải tìm hiểu kỹ thuật toán Dijsktra trước khi tìm hiểu thuật toán này.
Thuật toán Dijkstra, mang tên của nhà khoa học máy tính người Hà Lan Edsger Dijkstra, là một thuật toán giải quyết bài toán đường đi ngắn nhất trong một đồ thị có hướng không có cạnh mang trọng số âm.
a. Bài toán
Cho một đồ thị có hướng G=(V,E), một hàm trọng số w: E → [0, ∞) và một đỉnh nguồn s. Cần tính toán được đường đi ngắn nhất từ đỉnh nguồn s đến mỗi đỉnh của đồ thị. Ví dụ: Chúng ta dùng các đỉnh của đồ thị để mô hình các thành phố và các cạnh để mô hình các đường nối giữa chúng. Khi đó trọng số các cạnh có thể xem như độ dài của các con đường (và do đó là không âm). Chúng ta cần vận chuyển từ thành phố s đến thành phố t. Thuật toán Dijkstra sẽ giúp chỉ ra đường đi ngắn nhất chúng ta có thể đi. Trọng số không âm của
các cạnh của đồ thị mang tính tổng quát hơn khoảng cách hình học giữa hai đỉnh đầu mút của chúng. Ví dụ: với 3 đỉnh A, B, C đường đi A-B-C có thể ngắn hơn so với đường đi trực tiếp A-C.
b. Chứng minh
Ý tưởng của chứng minh như sau:
Chúng ta sẽ chỉ ra, khi một đỉnh v được bổ sung vào tập S, thì d[v] là giá trị của đường đi ngắn nhất từ nguồn s đến v.
Theo định nghĩa nhãn d, d[v] là giá trị của đường đi ngắn nhất trong các đường đi từ nguồn s, qua các đỉnh trong S, rồi theo một cạnh nối trực tiếp u-v đến v.
Giả sử tồn tại một đường đi từ s đến v có giá trị bé hơn d[v]. Như vậy trong đường đi, tồn tại đỉnh giữa s và v không thuộc S. Chọn w là đỉnh đầu tiên như vậy.
Đường đi của ta có dạng s - ... - w - ... - v. Nhưng do trọng số các cạnh không âm nên đoạn s - ... - w có độ dài không lớn hơn hơn toàn bộ đường đi, và do đó có giá trị bé hơn d[v].
Mặt khác, do cách chọn w của ta, nên độ dài của đoạn s - ... - w chính là d[w]. Như vậy d[w] < d[v], trái với cách chọn đỉnh v. Đây là điều mâu thuẫn. Vậy điều giả sử của ta là sai. Ta có điều phải chứng minh.
Trong khoa học máy tính, A* là một lựa chọn tốt nhất đồ thị tìm kiếm thuật toán mà tìm thấy đường dẫn chi phí ít nhất định ban đầu từ một nút tới một nút mục tiêu (trong một hoặc nhiều mục tiêu có thể). Nó sử dụng một khoảng cách, cộng với chi phí năng Heuristic (thường được ký hiệu là f (x))
để xác định thứ tự tìm kiếm thăm nút trong cây. Khoảng cách + giá Heuristic là một tổng của hai chức năng:
- Đường dẫn - chi phí hoạt động, đó là chi phí từ nút bắt đầu đến nút hiện tại (thường được ký hiệu là g (x)).
- Và một “Admissible Heuristic ước lượng” khoảng cách đến mục tiêu (thường được ký hiệu là h (x)).
H(x) là một phần của f (chức năng) x phải là một Admissible Heuristic; có nghĩa là, nó không được đánh giá cao khoảng cách đến mục tiêu. Vì thế cho một ứng dụng như định tuyến, h(x) có thể đại diện cho khoảng cách đường thẳng đến mục tiêu, vì đó là khoảng cách nhỏ nhất có thể giữa hai điểm.
Nếu h đáp ứng các điều kiện bổ sung h x d x, y h y cho cạnh mỗi x, y của đồ thị (d nghĩa là chiều dài của cạnh đó) sau đó được gọi là h không thay đổi hay nhất quán. Trong trường hợp này A* có thể được thực hiện hiệu quả hơn - khoảng nói, nút không cần phải được xử lý nhiều hơn một lần (xem đóng đặt dưới đây) - và trong thực tế, A* tương đương với chạy thuật toán Dijkstra's với chi phí giảm:
d'(x, y): = d(x,y) - h(x) + h(y)
Thuật toán này được mô tả lần đầu vào năm 1968 bởi Peter Hart, Nils Nilsson, và Bertram Raphael Thuật toán này đã được khái quát hóa thành một thuật toán tìm kiếm Heuristic hai chiều.
A* là sự lựa chọn phổ biến nhất, bởi vì nó khá linh hoạt và có thể được sử dụng trong nhiều hoàn cảnh.
A* là đồ thị như các thuật toán tìm kiếm khác nhưng khác ở chỗ nó có khả năng có thể tìm kiếm một khu vực rộng lớn của bản đồ. Nó giống như thuật toán Dijkstra trong đó nó có thể được sử dụng để tìm một con đường ngắn nhất. Nó giống như tham lam nhất ở chỗ nó có thể sử dụng một Heuristic để hướng dẫn chính nó.
3.2.2. Chi tiết thuật toán A*
Giả sử rằng có một người muốn đi từ điểm A tới điểm B. Giả định rằng một bức tường ngăn cách hai điểm. Điều này được minh họa bằng hình dưới
đây, với màu xanh lá cây là một điểm khởi đầu A, và màu đỏ là kết thúc điểm B và hình chữ nhật màu xanh là bức tường ở giữa (hình 3.2).
Hình 3.2
Ở đây chúng tôi đã phân chia khu vực tìm kiếm thành 1 lưới ô vuông như hình vẽ để đơn giản hóa khu vực tìm kiếm, đây là bước đầu tiên.
Phương pháp này đặc biệt làm giảm diện tích để tìm kiếm một mảng hai chiều đơn giản. Mỗi mục trong mảng đó đại diện cho một trong các hình vuông trên khu vực tìm kiếm, và tình trạng của nó được ghi lại như di chuyển hoặc đứng yên. Đường đi được tìm thấy khi xuất hiện các ô vuông liên tiếp đi từ A đến B.
Các ô vuông trên đường đi gọi là các “nút”. Các nút có thể được đặt ở bất cứ đâu trên khu vực tìm kiếm.
a. Bắt đầu tìm kiếm
Khi chúng ta đã đơn giản hóa khu vực tìm kiếm và quản lý được các “nút”, bước tiếp theo cần làm là tìm kiếm đường đi ngắn nhất từ A đến B, bắt đầu từ A, kiểm tra các hình vuông liền kề và tìm kiếm cho đến khi tìm thấy B.
- Bắt đầu từ A, sau đó thêm vào một danh sách mở các hình vuông liền kề A. Về cơ bản đây là danh sách các ô vuông cần kiểm tra để tìm ra đường đi đến B.
- Tất cả các hình vuông có thể truy cập hoặc di chuyển giáp với A, hình 3.1 hoặc các điểm không thuận lợi, thêm chúng vào danh sách mở. A là mốc quan trọng để theo dõi đường đi đến B.
- Chọn 1 điểm vuông trong danh sách mở làm điểm bắt đầu tiếp theo và đưa vào “danh sách đóng” khi F là nhỏ nhất.
Hình dưới đây minh họa cho công việc trên.
Hình 3.3
Chìa khóa xác định hình vuông để tìm ra con đường ngắn nhất là phương trình sau đây:
FGH Trong đó:
+ G là chi phí di chuyển để di chuyển từ A đến điểm khởi đầu cho một hình vuông trên khu vực tìm kiếm.
+ H là chi phí ước tính để di chuyển, từ đó đưa ra điểm vuông trên khu vực tìm kiếm đến đích cuối cùng. Chúng ta thực sự không biết khoảng cách thực tế cho đến khi tìm thấy con đường đi đến B.
Con đường được tìm thấy khi đi qua nhiều danh sách mở và hình vuông được chọn khi F là nhỏ nhất.
Trong ví dụ này, ta quy ước G=10 với di chuyển ngang, dọc và G=14 với di chuyển chéo (ta sử dụng 10 và 14 bởi vì khoảng cách thực tế để di chuyển theo đường chéo là căn bậc hai của 2, hay khoảng 1,414 lần chi phí di chuyển theo chiều ngang hoặc theo chiều dọc).
H có thể được tính bằng nhiều cách. Ở đây chúng tôi chọn phương pháp Manhattan. Với phương pháp này có thể tính được tổng số hình vuông di chuyển theo chiều ngang, dọc để đến đích mà không tính đến các chướng ngại vật, sau đó nhân tổng đó với 10.
Hình 3.4
Tiếp tục tìm kiếm
Để tiếp tục tìm kiếm chúng ta chọn ra hình vuông có F nhỏ nhất trong danh sách mở. So với hình vuông đã chọn, ta làm như sau:
- Đưa hình vuông được chọn từ danh sách mở vào danh sách đóng. - Kiểm tra tất cả các ô vuông kề bỏ qua những hình vuông có trong danh sách đóng hoặc không di chuyển (bức tường hình 3.2). Thêm hình vuông vào danh sách mở nếu như nó chưa có trong danh sách mở.
- Nếu một hình vuông liền kề đã được vào danh sách mở, kiểm tra G cho hình vuông đó là thấp hơn. Nếu không, không làm bất cứ điều gì. Mặt khác,
nếu chi phí G của các đường dẫn mới là thấp hơn, thay đổi các vuông kề bên vuông lựa chọn. Cuối cùng, tính toán lại cả F và G điểm của hình vuông đó.
Các bước trên được minh họa bằng hình vẽ dưới đây:
Hình 3.5
Hình 3.7
Cuối cùng ta tìm ra được đường đi từ A→B theo thuật toán A* như hình 3.8.
Hình 3.8
b. Tóm lược thuật toán A*
Từ giải thích chi tiết bằng ví dụ trên ta tóm lược lại được phương pháp A* như sau:
- Lặp lại như sau:
+ Chọn hình vuông F chi phí thấp nhất trong danh sách mở. + Chuyển nó vào danh sách đóng.
- Đối với mỗi ô vuông 8 cạnh vuông này.
- Nếu nó không di chuyển hoặc nếu nó nằm trong danh sách đóng cửa, bỏ qua nó. Nếu không làm như sau:
+ Nếu nó không có trong danh sách mở, thêm nó vào danh sách mở… Làm cho hiện tại khu vực tìm kiếm chính của hình vuông này bản ghi F, G, H và chi phí của nó.
+ Nếu đó là trong danh sách đã được mở, kiểm tra xem đường dẫn này để mà vuông là tốt hơn, bằng cách sử dụng G chi phí như là thước đo... Một G thấp hơn chi phí có nghĩa rằng đây là một con đường tốt hơn. Nếu vậy, thay đổi các vuông chính của khu vực tìm kiếm vào vuông hiện tại và tính toán lại các G và điểm F của khu vực tìm kiếm.
- Dừng khi:
+ Thêm các mục tiêu vuông vào danh sách đóng cửa, trong đó đường dẫn trường hợp đã được tìm thấy.
+ Không tìm thấy những vuông mục tiêu và danh sách mở trống. Trong trường hợp này, không có đường dẫn.
3.3. Cài đặt giải thuật
3.3.1. Cài đặt giải thuật
Lập trình C# trên visual studio 2010.