Giới thiệu về thuật toán A*

Một phần của tài liệu LẬP TRÌNH GAME ỨNG DỤNG THUẬT TOÁN A (Trang 27 - 36)

1.3.1. Sơ lược các bài toán tìm đường đi ngắn nhất

Trong các ứng dụng thực tế, bài toán tìm đường đi ngắn nhất giữa hai đỉnh của một đồ thị liên thông có một ý nghĩa to lớn, có thể dẫn về bài toán như vậy nhiều bài toán thực tế quan trọng. Ví dụ, bài toán chọn một hành trình tiết kiệm nhất (theo tiêu chuẩn hoặc khoảng cách hoặc thời gian hoặc chi

phí) trên một mạng giao thông đường bộ, đường thủy,… hay bài toán chọn một phương pháp tiết kiệm nhất để đưa ra một hệ thống động lực từ trạng thái xuất phát đến trạng một trạng thái đích, bài toán lập lịch thi công các công các công đoạn trong một công trình thi công lớn, bài toán lựa chọn đường truyền tin với chi phí nhỏ nhất trong mạng thông tin… Có rất nhiều phương pháp để giải các bài toán như vậy. Thế nhưng thông thường, các thuật toán được xây dựng dựa trên cơ sở lý thuyết đồ thị tỏ ra là các thuật toán có hiệu quả cao nhất.

Ta đã biết trong lí thuyết đồ thị bài toán tìm đường đi ngắn nhất nguồn đơn là bài toán tìm đường đi ngắn nhất giữa 2 đỉnh sao cho tổng trọng số các cạnh tạo nên đường đi đó là nhỏ nhất. Có nhiều thuật toán để giải quyết bài toán này:

- Thuật toán Dijkstra: giải bài toán nguồn đơn nếu tất cả các trọng số đều không âm. Thuật toán này có thể tính toán tất cả các đường đi ngắn nhất từ một đỉnh xuất phát cho trước S tới mọi đỉnh khác mà không làm tăng thời gian chạy.

- Thuật toán Bellman-Ford: giải bài toán nguồn đơn trong trường hợp trọng số có thể có giá trị âm.

- Thuật toán tìm kiếm A*: giải bài toán nguồn đơn sử dụng Heuristics để tăng tốc độ tìm kiếm.

- Thuật toán Floyd-Warshall: giải bài toán đường đi ngắn nhất cho mọi cặp đỉnh.

- Thuật toán Johnson: giải bài toán đường đi ngắn nhất cho mọi cặp đỉnh, có thể nhanh hơn thuật toán Floyd-Warshall trên các đồ thị thưa.

- Lý thuyết nhiễu (Perturbation theory): tìm đường đi ngắn nhất địa phương (trong trường hợp xấu nhất).

Trong đề tài này sẽ quan tâm đến thuật toán tìm kiếm đường đi ngắn nhất A*, thuật toán này dựa trên hàm đánh giá Heuristic để tìm đường đi tối ưu nhất.

1.3.2. Thuật toán A*

a) Giới thiệu về thuật toán A*

Thuật toán A* được mô tả lần đầu tiên năm 1986 bởi Peter Hart, Nils Nilso và Bertram Raphael. Trong báo cáo của họ, thuật toán được gọi là thuật toán A, khi sử dụng thuật toán này với một hàm đánh giá Heuristic thích hợp sẽ thu được hoạt động tối ưu, do đó mà có tên là thuật toán A*.

Trong khoa học máy tính, A* là một thuật toán tìm kiếm trong đồ thị.

Thuật toán này tìm một đường đi từ nút khởi đầu tới một nút đích cho trước (hoặc tới một nút thỏa mãn điều kiện đích). Thuật toán sử dụng một đánh giá Heuristic để xếp loại từng nút theo ước lượng về tuyến đường tốt nhất đi qua nút đó. Thực hiện duyệt các nút theo thứ tự của đánh giá Heuristic này. Hàm đánh giá Heuristic là các hàm đánh giá thô, giá trị của hàm phụ thuộc vào trạng thái hiện tại của bài toán tại mỗi bước giải, đánh giá chi phí để đi từ nút hiện tại n đến nút đích (mục tiêu). Nhờ giá trị này, ta có thể chọn được cách hành động tương đối hợp lý trong từng bước của thuật giải. Do đó, thuật toán A* là một ví dụ của tìm kiếm theo lựa chọn tốt nhất (best-first search).

b) Mô phỏng thuật toán trên cây đồ thị Ý tưởng:

Xét bài toán tìm đường, A* sẽ xây dựng tăng dần các tuyến đường từ đỉnh xuất phát đến khi nó tìm thấy đường đi chạm đến đích. Để xác định khả năng dẫn đến đích, A* sử dụng một đánh giá Heuristic về khoảng cách từ một điểm bất kì cho trước đến đích.

A* đảm bảo tính đầy đủ và tối ưu, nó luôn tìm thấy đường đi ngắn nhất nếu tồn tại một đường đi như thế. Đầy đủ và tối ưu hơn các thuật toán tìm đường đi khác ở chỗ nó không chỉ ước lượng khoảng cách còn lại (nhờ đánh giá Heuristic) mà còn tính khoảng cách đã đi qua để tìm được đường đi ngắn nhất.

Hàm đánh giá Heuristic:

A* lưu giữ một tập các đường đi qua đồ thị, bắt đầu từ nút xuất phát. Tập lời giải này được lưu trong một hàng đợi ưu tiên (priority queue). Thứ tự ưu tiên gán cho một đường đi x được quyết định bởi hàm đánh giá Heuristic:

f(n) = g(n) + h(n)

Với: - g(n) là chi phí từ nút gốc cho đến nút hiện tại n.

- h(n) là chi phí ước lượng từ nút hiện tại n tới đích.

- f(n) là chi phí tổng thể ước lượng của đường đi qua nút hiện tại n đến đích.

Một ước lượng Heuristic h(n) được xem là chấp nhận được nếu với mọi nút n sao cho: 0 < h(n) <h*(n)

Trong đó h*(n) là chi phí thật (thực tế) để đi từ nút n đến đích.

Bài toán trên cây đồ thị.

Trong bài toán tìm đường đi từ Arad đến Bucharest, sử dụng: h(n) = Ước lượng khoảng cách đường thẳng (đường chim bay) từ thành phố hiện tại n đến Bucharest. Sơ đồ minh họa hình 1.8.

Hình 1.12: Cây đồ thị tìm kiếm đường đi từ Arad đến Bucharest

Các bước thực hiện tìm kiếm thuật toán A*

Bước 1:

Bắt đầu từ Arad, lúc này chi phí từ nút gốc đến nút hiện tại g(n) = 0, chi phí từ nút hiện tại tới đích h(n) = 366 nên sẽ có giá trị f(n) = 0 + 366 = 366.

Hình 1.13: Xuất phát bắt đầu từ Arad Bước 2:

Hình 1.14: Từ Arad duyệt đến Sibi

Tiếp tục từ nút Arad ta tìm được 3 nút có thể đi tiếp theo là Sibi, Tim, Zer. Dùng cách tính f(n) tương tự ta tìm được Sibi là nút đi tiếp theo với f(n)

= 399, trong đó chi phí từ nút gốc đến nút hiện tại g(n) = 140, chi phí ước lượng h(n) = 253. Giá trị f(n) tại Sibi là bé nhất trong 3 nút nên Sibi sẽ là lựa chọn ưu tiên tiếp theo. (Xem hình 1.14).

Bước 3:

Hình 1.15: Từ Sibi duyệt đến Rimin

Tương tự với 2 bước trên ta xác đinh được Rimin là điểm được chọn tiếp theo đi từ nút Sibi với giá trị f(n) = 413. (Xem hình 1.15).

Bước 4:

Hình 1.16: Từ Rimin quay về Fagar

Tại nút Rimin này ta đi tiếp được 3 nút tiếp theo là Crai, Pite và Sibi, lúc này bộ nhớ đã lưu giá trị f(n) của Fagar rồi nền sẽ lựa chọn Fagar là nút tiếp theo để đi vì giá trị f(n) của Fagar bé nhất trong các giá trị f(n) đã duyệt. Ở bước này không cần quay lại nút Sibi để duyệt lại, đây là một ưu điểm của thuật toán A* vì nó lưu lại các giá trị f(n) của những nút nó đã đi qua.

Bước 5:

Hình 1.17: Từ Fagar đi đến Pite

Tiếp tục từ Fagar ta tìm được 2 nút đi tiếp theo là Sibi và Bucharest. Tại đây có vẻ là đã tìm được tới đích Bucharest nhưng thuật toán lại tiếp tục xét hàm đánh giá Heuristic thay vì dừng lại ở giá trị f(n) = 450. Lúc này trong bộ nhớ Pite là nút có f(n) = 417 là bé nhất trong các nút đã duyệt. Chuyển đến Pite để tiếp tục tìm kiếm. (Xem hình 1.17).

Bước 6:

Ở nút Pite sẽ đi đến 3 nút tiếp theo và tại đây đã đến được đích Bucharest với giá trị f(n) = 418 như hình 1.14. Giá trị f(n) này cho thấy chi phí đi đến đích từ điểm xuất phát ít hơn nhiều so với f(n) tại điểm dừng ở

bước 5 (f(n) = 450). Việc xét hàm đánh giá như vậy giúp thuật toán A* thực hiện được tối ưu đáng kể độ dài đường đi, tuy nhiên việc xét và lưu từng giá trị vẫn là một điểm hạn chế về thời gian và bộ nhớ của thuật toán.

Hình 1.18: Từ Pite lựa chọn được đích đến Bucharest

c) Các đặc điểm của thuật toán A*

- Nếu không gian các trạng thái là hữu hạn có giải pháp để tránh việc xét (lặp) lại các trạng thái, thì giải thuật A* là hoàn chỉnh (tìm được lời giải) nhưng không đảm bảo là tối ưu.

- Nếu không gian các trạng thái là hữu hạn không có giải pháp để tránh việc xét (lặp) lại các trạng thái, thì giải thuật A* là không hoàn chỉnh (không đảm bảo tìm được lời giải).

- Nếu không gian các trạng thái là vô hạn, thì giải thuật A* là không hoàn chỉnh (không đảm bảo tìm được lời giải)

d) Rút ra nhận xét về thuật toán A*

- Tính hoàn chỉnh : Thuật toán A* có tính hoàn chỉnh nhưng nếu có nhiều các nút có chi phí f < f(G) thì không đảm bảo.

- Độ phức tạp về thời gian : Bậc của hàm mũ – Số lượng các nút được xét là hàm mũ của độ dài đường đi của lời giải.

- Độ phức tạp về bộ nhớ : Lưu giữ tất cả các nút trong bộ nhớ.

- Tính tối ưu : Thuật toán A* có tính tối ưu vì trong quá trình tìm kiếm thuật toán này phát triển chủ yếu theo hướng tới đích, không phát triển theo mọi hướng như các thuật toán khác chẳng hạn như Breadth First Search.

Hình 1.19: Thuật toán A* phát triển theo hướng tới đích nhưng đảm bảo tính tối ưu

Một phần của tài liệu LẬP TRÌNH GAME ỨNG DỤNG THUẬT TOÁN A (Trang 27 - 36)

Tải bản đầy đủ (DOCX)

(56 trang)
w