Trong đó nhóm em thực sự tâm đắc với phần các thuật toán tìm kiếm và quyết định thực hiện một đề tài với chủ đề là: thực hiện game giải mê cung sử dụng thuật toán tìm đườ
Trang 1ĐẠI HỌC QUỐC GIA HÀ NỘI TRƯỜNG ĐẠI HỌC KHOA HỌC TỰ NHIÊN
BÁO CÁO GAME GIẢI MÊ CUNG SỬ DỤNG A*
HÀ NỘI, 2023
Trang 2MỤC LỤC
LỜI NÓI ĐẦU 3
1 Tổng quan 4
1.1 Đặt vấn đề. 4
1.2 Giải thuật tìm kiếm 4
1.3 Tổng quan về các giải thuật tìm kiếm 4
2 Phương pháp giải quyết bài toán 5
2.1 Lịch sử của A* 5
2.2 Ý tưởng giải quyết bài toán 5
2.3 Đánh giá giải thuật A* 9
3 Các khó khăn gặp phải và cách khắc phục 10
4 Đề xuất phương pháp cải tiến giải thuật A* 10
5 Tổng kết 10
6 Tài liệu tham khảo 11
Trang 3LỜI NÓI ĐẦU
Lời đầu tiên nhóm em xin được gửi lời cảm ơn tới thầy Thân Quang Khoát đã thực hiện giảng dạy môn học nhập môn AI Sau khi hoàn thành môn học bọn em đã thu được thêm rất nhiều kiến thức mới bổ ích Trong đó nhóm em thực sự tâm đắc với phần các thuật toán tìm kiếm và quyết định thực hiện một đề tài với chủ đề là: thực hiện game giải mê cung sử dụng thuật toán tìm đường A* Đây là một thuật toán tìm kiếm thõa mãn ràng buộc
Lý do chọn đề tài này của nhóm em đó là vì đây là một đề rất thú vị, có tính ứng dụng cao trong thực tiễn Có thể giúp chúng ta tìm được đường đi một cách tối ưu trong việc xây dựng bản đồ các tuyến đường hay trong các lĩnh vực lĩnh vực trí tuệ nhân tạo, các hệ thống xe tự hành,…
Trang 41 Tổng quan
1.1 Đặt vấn đề
Sử dụng các giải thuật tìm kiếm A* để tìm đường đi tối ưu nhất giữa hai điểm bắt đầu
và đích đến đã biết trong mê cung Trong đó mê cung sẽ có các lối đi và tường là phần không đi được, điểm bắt đầu và đích đến sẽ được tạo mới một cách ngẫu nhiên
1.2 Giải thuật tìm kiếm
Định nghĩa thuật toán tìm kiếm: Trong ngành khoa học máy tính, một giải thuật tìm
kiếm là một thuật toán lấy đầu vào là một bài toán và trả về kết quả là một lời giải cho bài toán đó, thường là sau khi cân nhắc giữa một loạt các lời giải có thể Hầu hết các thuật toán được nghiên cứu bởi các nhà khoa học máy tính để giải quyết các bài toán đều là các thuật toán tìm kiếm Tập hợp tất cả các lời giải có thể đối với một bài toán được gọi là không gian tìm kiếm Thuật toán thử sai (brute-force search) hay các thuật toán tìm kiếm "sơ đẳng" không có thông tin sử dụng phương pháp đơn giản nhất và trực quan nhất Trong khi đó, các thuật toán tìm kiếm có thông tin sử dụng heuristics để áp dụng các tri thức về cấu trúc của không gian tìm kiếm nhằm giảm thời gian cần thiết cho việc tìm kiếm
Chúng ta đã được học rất nhiều loại giải thuật tìm kiếm như là tìm kiếm trên cây, tìm kiếm trên đồ thị, tìm kiếm đối kháng, tìm kiếm thỏa mãn ràng buộc,…
Trong quá trình học ta đã được học với một số giải thuật tìm kiếm cơ bản trong đồ thị
cơ bản như: BFS, UCS, DFS, DLS, IDS
Hay các giải thuật tìm kiếm với tri thức bổ sung: best-first search, A*, giải thuật tìm kiếm thỏa mãn một ràng buộc cho trước chằng hạn
1.3 Tổng quan về các giải thuật tìm kiếm
Đối với các giải thuật tìm kiếm cơ bản thì ta sẽ thực hiện bằng việc xây dựng các nút
từ nút gốc và tìm ra nút đích của bài toán
BFS (giải thuật tìm kiếm theo chiều rộng) chúng ta sẽ tiến hành phát triển các nút
bắt đầu từ nút gốc theo chiều rộng và thứ tự độ sâu tăng dần Chúng ta sẽ ghé qua tất
cả các nút hoặc cho tới khi tìm được nút đích Tuy nhiên thuật toán này quá phức tạp về mặt thời gian và bộ nhớ dù nó có thể có tính hoàn chỉnh
UCS (giải thuật tìm kiếm với chi phí cực tiểu) ta tiến hành phát triển các nút có chi
phí thấp nhất (với chi phí từ nút gốc tới nút đang xét là tăng dần) đảm bảo tính hoàn chỉnh, thời giản và bộ nhớ phụ thuộc vào tổng số nút có chi phí <= chi phí của lời giải tối ưu
DFS (giải thuật tìm kiếm theo chiều sâu) ta phát triển các nút theo chiều sâu của
cây với cấu trúc LIFO (Last In First Out) tức là nút nào vào trước thì ở độ sâu tiếp theo ta sẽ xét nhánh đó Ta sẽ tập trung xét theo một nhánh cho tới khi tìm được đích hoặc đi mãi và không bao giờ tìm được nếu cây có độ sâu vô hạn Nếu gặp đường cụt thì ta sẽ quay lại và xét nhánh khác
Tính hoàn chỉnh của giải thuật này là không có, thời gian tìm kiếm thì có thể rất lâu
và tốn rất nhiều bộ nhớ Không có tính tối ưu
IDS (giải thuật tìm kiếm sâu dần)
Đối với giải thuật này ta vẫn áp dụng giải thuật tìm kiếm theo chiều sâu tuy nhiên tại mỗi bước ta sẽ giới hạn độ sâu cho nó sau đó phát triển các nút tại đô sâu giới hạn đó,
Trang 5nếu như không tìm được kết quả ta sẽ tăng giới hạn độ sâu lên cứ như vậy cho tới khi tìm ra kết quả
Giải thuật này đảm bảo tính hoàn chỉnh, tiết kiệm thời gian cũng như bộ nhớ Đây là một giải thuật tối ưu nếu cho phí cho mỗi bước đi đều bằng một
Các giải thuật tìm kiếm với tri thức bổ sung: các giải thuật này hiệu quả hơn các giải thuật tìm kiếm cơ bản và có tính ứng dụng cao trong thực tiễn Phải kể đến như là greedy best first search hay A*
Đối với greedy best first search thì ý tưởng là sử dụng thêm một hàm đánh giá h(n)
cho mỗi nút cây tìm kiếm, hàm đánh giá được sử dụng ở đây là hàm heuristic Heuristic là hàm dùng để đánh giá chi phí từ nút hiện tại đang đứng tới nút đích Tập trung vào phát triển các nút có vẻ gần với nút mục tiêu nhất
Giải thuật này không đảm bảo tính hoàn chỉnh, độ phức tạp về thời gian và tốn bộ nhớ, không mang lại sự tối ưu
Đối vói A* đây là giải thuật tốt hơn của giải thuật best first search, thay vì chỉ dùng có
1 hàm h(n) thì giờ đây ta dùng thêm một hàm f(n) tính toán chi phí từ nút gốc đến nút hiện tại đang đứng Ta sẽ lựa chọn đi các nút mà có f(n) + g(n) là nhỏ nhất
2 Phương pháp giải quyết bài toán
Để giải quyết bài toán này thì chúng ta sẽ sử dụng giải thuật tìm kiếm A* để tìm đường đi ngắn nhất giữa hai điểm bắt đầu và đích đến cho trước
Trước khi đi vào giải quyết bài toán chúng ta sẽ tìm hiểu xem A* là gì và nó có gì đặc biệt để có thể giải quyết bài toán này
2.1 Lịch sử của A*
Thuật toán A* được mô tả lần đầu vào năm 1968 bởi Peter Hart, Nils Nilsson và Bertram Raphael Trong bài báo của họ, thuật toán được gọi là A* khi sử dụng thuật toán này đối với một đánh giá heuristic thích hợp sẽ thu được hoạt động tối ư, do đó
mà có tên A*
Năm 1964, Nils Nilsson phát minh ra một phương pháp tiếp cận dựa trên khám phá để tăng tốc độ của thuật toán Dijkstra Thuật toán này được gọi là A1
Năm 1967, Bertram Raphael đã cải thiện tốc độ của thuật toán này nhưng không thể tối ưu được nó Ông gọi thuật toán này là A2 Sau đó năm 1968 Peter E.Hart đã giới thiệu một đối số chứng minh A2 là tối ưu khi sử dụng thuật toán này với một đánh giá heuristic thích hợp sẽ thu được hoạt động tối ưu
Chứng minh của ông về thuật toán này cũng bao gồm một phần cho thấy rằng các thuật toán A2 mới là thuật toán tốt nhất có thể được đưa ra các điều kiện Do đó ông đặt tên cho thuật toán mới là thuật toán A*
A* ban đầu là thuật toán tìm đường đi có chi phí thấp nhất khi mà chi phí của đường
đi bằng tổng các chi phí của nó Tuy nhiên người ta đã chứng minh là sẽ tìm được đường đi tối ưu cho bất kỳ bài toán nào nếu như nó thỏa mãn ràng buộc về chi phí
2.2 Ý tưởng giải quyết bài toán
Xét bài toán tìm đường, bài toán mà A* thường được dùng để giải A* được xây dựng tăng dần tất cả các tuyến đường từ điểm xuất phát cho tới khi nó tìm thấy được một đường đi chạm tới đích Tuy nhiên cũng như các thuật toán tìm kiếm khác đó là nó lại chỉ tìm các đường đi vô cớ dẫn về đích
Trang 6Thuật toán này sử dụng một đánh giá heuristic để sắp xếp các nút theo ước lượng về tuyến đường tốt nhất đo qua nút đó Nó sẽ duyệt các nút đã sắp xếp và quyết định xem nút tiếp theo nó sẽ đi qua là nút nào
Ta sẽ có f(n) = g(n) + h(n) (1)
Trong đó thì g(n) là khoảng cách từ nút hiện tại đang đứng tới nút đích, và h(n) là ước lượng theo đường chim bay khoảng cách từ nút hiện tại đang đứng tới đích Có rất nhiều cách để tính toán h(n), ở đây ta sẽ sử dụng khoảng cách Manhattan để tính toán khoảng cách h(n)
Khoảng cách Manhattan còn được gọi là khoảng cách 𝐿1 hay khoảng cách trong thành phố, là một dạng khoảng cách giữa hai điểm trong không gian Euclid với hệ tọa độ Descartes Đại lượng này được tính bằng tổng chiều dài của hình chiếu của đường thẳng nối hai điểm này trong hệ trục tọa độ Descartes
Ta có khoảng cách Manhattan giữa hai điểm 𝑃1(𝑥1, 𝑥2) và 𝑃2(𝑥2, 𝑦2) là
|𝑥1− 𝑥2| + |𝑦1− 𝑦2|
Nếu như mà f(n) đánh giá nút nào là bé nhất thì sẽ đi theo nút đó
Điều này khác biệt với các thuật toán tìm đường khác khiến cho A* trở nên đầy đủ và tối ưu Nó sẽ hoàn toàn tìm được đường đi ngắn nhất nếu tồn tại một đường đi như thế Tuy nhiên A* sẽ không đảm bảo sẽ chạy nhanh hơn các thuật toán tìm kiếm khác
Ta có thể hiểu ý tưởng thuật toán này thông qua ví dụ dưới đây:
Hình 1: bản đồ thành phố
Trang 7Bảng 1: tên các thành phố và ước lượng khoảng cách đến đích tương ứng
Yêu cầu bài toán: hãy sử dụng A* để tìm đường đi ngắn nhất từ thành phố Arad đến Bucharest
Lời giải:
Bước 1: xuất phát từ nút đầu tiên, dựa vào bảng 1 ta có chi phí ước lượng từ điểm bắt đầu tới đích cần đến h(n) của Arad là 366 và g(n) = 0 do ta bắt đầu xuất phát từ thành
phố Arad Từ (1) ta sẽ tính ra f(n) = 0 + 366 = 366
Hình 2: thực hiện giải thuật tìm đường A* bước một
Bước 2: từ thành phố Arad ta sẽ có thể đi tới ba thành phố là Sibiu, Timisoara và Zerind Ta sẽ dựa vào bảng lấy ra giá trị ước lượng h(n) và nhìn từ hình 1 ta sẽ thấy khoảng cách từ thành phố bắt đầu tới thành phố hiện tại đang đứng đặt là g(n), ta sẽ tính ra được f(n) Nếu f(n) của thành phố nào là nhỏ nhất thì ta sẽ chọn đi qua thành phố đó
Hình 3: thực hiện giải thuật tìm đường A* bước hai
Trang 8Hình 4: thực hiện giải thuật tìm đường A* bước ba
Hình 5: thực hiện giải thuật tìm đường A* bước bốn
Hình 6: thực hiện giải thuật tìm đường A* bước năm
Hình 7: tìm được đích cần đến
Trang 9Thực hiện tương tự như bước 2 cuối cùng chúng ta sẽ thu được chi phí đường đi ngắn
nhất từ Arad đến Bucharest là 418 và truy vết ngược trở lại các nút chúng ta đã đi qua
sẽ tìm được đường đi tối ưu nhất đến đích
Với bài toán thực tế đặt ra chúng ta sẽ khởi tạo một ma trận kích thước 10x10 Các
điểm bắt đầu và điểm kết thúc được khởi tạo một cách ngẫu nhiên sau mỗi lần ta chạy
lại chương trình Ma trận này sẽ có các đường đi và tường là những ô không thể đi
qua được Nhiệm vụ của chúng ta đó là sử dụng A* để tìm đường đi tối ưu đến đích
Chúng ta sẽ thực hiện như sau:
1 xác định điểm bắt đầu và điểm kết thúc
2 khởi tạo một hàng đợi ưu tiên, thêm điểm bắt đầu và điểm kết thúc bằng hàm chi
phí
3 lặp lại các bước phía dưới cho đến khi tìm thấy đường đi tối ưu:
3.1 lấy ra nút có chi phí dự đoán thấp nhất khỏi hàng đợi
3.2 kiểm tra xem nút này có phải điểm kết thúc hay không Nếu có, đường đi này là
tối ưu
3.3 nếu không, tạo ra các nút con từ nút hiện tại và tính toán từ điểm bất kỳ đến nút con và chi phí dự đoán từ nút con đến điểm kết thức bằng hàm chi phí
3.4 thêm các nút con vào hàng đợi ưu tiên và cập nhật thông tin nếu chi phí dự đoán
thấp hơn nút đã có trong hàng đợi
4 nếu không tìm thấy đường đi tới điểm kết thúc thì ta kết luận không tồn tại đường
đi tới địch
5 truy vết đường đi tối ưu từ điểm kết thúc tới điểm bắt đầu bằng các nút đã được lưu
lại trong quá trình tìm kiếm
2.3 Đánh giá giải thuật A*
Nếu không gian trạng thái là hữu hạn và tránh được việc mắc vào các vòng lặp trạng
thái thì giải thuật A* có tính hoàn chỉnh tuy nhiên không dám đảm bảo tính tối ưu
Nếu ta không thể tránh được việc lặp trạng thái hoặc không gian trạng thái không hữu
hạn thì giải thuật này không có tính hoàn chỉnh
Giải thuật A* có tính tối ưu nếu nó có thể tho mãn hàm heuristic là một ước lượng
chấp nhận được
Hàm heuristic h*(n) thỏa mãn ước lượng chấp nhận được nếu 0 =< h*(n) <= h(n),
trong đó h(n) là chi phí thực tế để đi từ nút hiện tại đang xét tới nút đích
Tính nhất quán trong giải thuật A*
Nếu heuristic h(x) được coi là nhất quán đơn điệu nếu thỏa mãn điều kiện bổ sung:
h(x) =< d(x, y) + h(y)
Trong đó:
- x là điểm ta đang xét
- y là mọi điểm lân cận với x
- d(x, y) là chi phí đi từ x tới y
Tức là đối với mọi điểm x và mỗi điểm lân cận y kế tiếp của x thì chi phí ước tính để
đến được đích từ x không lớn hơn chi phí đi từ x tới y cộng với chi phí ước tính để
đến đích từ y
Khi đó A* được đảm bảo tìm ra đường đi tối ưu không cần xử lý bất kỳ nút nào nhiều
hơn một lần Nghĩa là trong trường hợp hàm đánh giá là có thể chấp nhận được nhưng
Trang 10lại không nhất quán, thì tại một điểm sẽ bị mở rộng lặp lại tại mỗi khi tìm được đường
đi có chi phí tốt hơn
3 Các khó khăn gặp phải và cách khắc phục
A* tuy là một trong những giải thuật tìm đường phổ biến và hiệu quả nhất tuy nhiên khi xây dựng A* chúng ta vẫn gặp phải một số khó khăn như là:
- nếu chúng ta dự đoán hàm heuristic sai, thiếu thông tin có thể dẫn đến tìm đường sai
- quá tốn bộ nhớ, thời gian thực thi lâu: nếu như xây dựng mê cung quá lớn, nhiều nút dẫn đến phức tạp, ảnh hưởng hiệu suất
- do điếm bắt đầu và đích đến được khởi tạo ngẫu nhiên do đó có thể không tìm được đích đến: trong trường hợp không tồn tại đường đi từ điểm bắt đầu đến đích
- trường hợp gặp phải các vòng lặp có thể không thể thoát ra được dẫn đến không tìm được đường đi đến đích
4 Đề xuất phương pháp cải tiến giải thuật A*
Các giải thuật cải tiến của A* mà ta có thể nghĩ đến là kết hợp giữa A* và DFS tạo ra thuật toán tìm đường mới là IDA* Được sử dụng trong trường hợp không gian trạng thái của chúng ta là lớn và không có thông tin chi phí chính xác Thuật toán này cho phép ta tìm kiếm đường đi theo từng độ sâu ngày càng tăng cho đến khi tìm thấy đích Trong giải thuật này chúng ta cần đặt giới hạn (threshold) ban đầu bằng giá trị ước tính heuristic từ trạng thái bắt đầu tới trạng thái đích
Sử dụng tìm kiếm theo chiều sâu, thực hiện một lần tìm kiếm từ trạng thái bắt đầu với giới hạn (threshold) đã đặt Trong quá trình tìm kiếm, IDA* theo dõi giá trị chi phí tới trạng thái hiện tại (thường là tổng các giá trị heuristic đã xem xét) và so sánh với giới hạn Nếu chi phí vượt quá giới hạn, thuật toán sẽ dừng tìm kiếm tại đây
Nếu đích được tìm thấy, thuật toán kết thúc và trả về giải pháp tìm được
Nếu không tìm thấy đích trong một lần tìm kiếm theo chiều sâu giới hạn, tăng giới hạn bằng giá trị heuristic nhỏ nhất của các trạng thái không thể duyệt qua trong lần tìm kiếm trước đó
Tiếp tục lặp lại các bước sử dụng tìm kiếm theo chiều sâu và theo dõi giá trị chi phí cho tới khi tìm ra được đường đi tối ưu hoặc không còn trạng thái để duyệt
Ngoài ra ta có thể áp dụng phương pháp cắt tỉa alpha – beta để cắt tỉa đi các nhánh mà
ta cảm thấy k có tiềm năng hay không thể tìm được đường đi đến đích để giảm thiểu bộ nhớ và thời gian thực hiện
Ở đây ta còn sử dụng hàm heuristic thông minh tính bằng khoảng cách Manhattan để ước lượng chính xác chi phí đi từ nút hiện tại tới đích thay vì ước lượng một cách ngẫu nhiên Giúp tối ưu được rất nhiều cho bài toán đảm bảo tính tối ưu và tiết kiệm được rất nhiều thời gian tìm kiếm
5 Tổng kết
Thực hiện đề tài này đã giúp nhóm em tự mình giải quyết được bài toán thực tế tìm kiếm đường đi trong mê cung với chi phí nhỏ nhất giữa hai điểm ta đã biết Nếu rộng
ra là ta sẽ có thể ứng dụng được trong việc xác định được các tuyến đường tốt nhất để
đi trên bản đồ khi biết điểm bắt đầu và điểm kết thúc, hay tìm đường đi cho robot vượt chướng ngại vật và tìm đường về đích nhanh nhất,…
Qua đây chúng em đã học được thêm rất nhiều kiến thức để phục vụ cho việc học tập
và công việc sau này