You are on page 1of 13

Giới thiệu chung

Tham lam và A* đều thuộc dạng thuật toán tìm kiếm có thông tin:

- Sử dụng kiến thức cụ thể của vấn đề/bài toán đưa ra nhằm tìm ra giải pháp.

- Sử dụng một hàm heuristic tạo điều kiện cho việc truyền đạt kiến thức bổ sung về
vấn đề cho thuật toán.

So sánh với tìm kiếm mù/không có thông tin ở các thuật toán trước:

Giống nhau ở chỗ cả hai phương pháp tìm kiếm đều phải lấy thông tin từ đề bài/vấn
đề.

Khác nhau ở bảng dưới

CƠ SỞ TÌM KIẾM CÓ THÔNG TIN TÌM KIẾM KHÔNG THÔNG


TIN
SO SÁNH

CĂN BẢN Vận dụng kiến thức để tìm ra Chỉ sử dụng thông số/thông tin
hàm heuristic => các bước giải kỹ thuật theo phát biểu bài toán
và một quy luật cho trước

HIỆU QUẢ Cao (vì tiêu tốn ít thời gian và chi Trung gian
phí hơn)

GIÁ CẢ Thấp Tương đối cao

HIỆU SUẤT Nhanh hơn Chậm hơn

THUẬT TOÁN - Tham lam (kết quả đầu tiên tốt - Tìm kiếm theo chiều sâu (DFS)
nhất)
- Tìm kiếm theo chiều rộng
- A* (BFS)

- A* sâu dần (IDA*) - Tìm kiếm chi phí cực tiểu


(UCS)

- Tìm kiếm sâu dần (IDS)


2. Cụ thể từng thuật toán & Ví dụ

Tham lam – Kết quả đầu tiên tốt nhất

Lấy ví dụ là giờ mẹ các bạn cho các bạn 1 tờ 200k hay 2 tờ 100k, bạn sẽ chọn
tờ 200k, dù giá trị của 2 lựa chọn này là như nhau. Đó là thuật toán tham lam.

- Tên tiếng Anh: Greedy algorithm

- Khái niệm: Lựa chọn tối ưu ở mỗi bước đi để hi vọng tìm ra lời giải tối ưu toàn cục.

- Tính chất:

+ Là thuật toán dạng lặp.

+ Chọn giải pháp tốt nhất ở thời điểm hiện tại và giải bài toán con nảy sinh từ
lựa chọn. Các lựa chọn sau phụ thuộc vào lựa chọn trước đó nhưng không phụ thuộc
vào lựa chọn trong tương lai hay lời giải của bài toán con.

+ Quyết định từng lựa chọn sớm và thay đổi hướng đi của giải thuật theo các
lựa chọn đó.

+ Từng quyết định chỉ được duyệt 1 lần. Không bao giờ xét lại các quyết định
cũ.

- Nguyên lý:

Giả sử nghiệm của bài toán có thể biểu diễn dưới dạng một vector (x1, x2, ...,
xn), mỗi thành phần xi (i=1, 2, ..., n) được chọn ra từ tập Si.
Mỗi nghiệm của bài toán X = (x1, x2 , ... , x n) được xác định "độ tốt" bằng một
hàm ƒ(X)
=> Mục tiêu cần tìm nghiệm có giá trị ƒ(X) tối ưu (lớn/nhỏ nhát có thể)

Tư tưởng:
Xây dựng vector nghiệm X từng bước, bắt đầu từ vector không ( ).
Giả sử đã xây dựng được (k-1) thành phần (x1 x2, ..., xk-1) của nghiệm và khi
mở rộng nghiệm ta sẽ chọn xk "tốt nhất" trong các ứng cử viên trong tập Sk để được
(x1, x2, ..., xk). Việc lựa chọn như vậy được thực hiện bởi một hàm chọn. Cứ tiếp tục
như vậy cho đến khi xây dưng xong hết tất cả các thành phần của nghiệm.

Tổng quát băng pseudo code:


Thamlam(A ,S) { A là tập các ứng cử viên, S là tập nghiệm}
Bước 1: S=∅;
Bước 2: Khi A ≠ ∅ thực hiện các bước sau:
Bươc 2.1: X = Select(A);
Bước 2.2: A = A - {x};
Bước 2.3: Nếu S ∪ {x} Chấp nhận được thì S=S ∪ {x}

- Đánh giá:

+ Ưu điểm:

Thuật toán đơn giản, dùng ít bộ nhớ

Độ “phức tạp” rõ ràng – Phân tích thời gian chạy dễ dàng hơn

Nếu một thuật toán tham lam có thể chứng minh là tối ưu, nó sẽ thường được sử
dụng

vd. Kruskal và Prim => cây bao trùm nhỏ nhất

Dijikstra => đường đi ngắn nhất

+ Nhược điểm

Thường kết quả của thuật toán sẽ không tối ưu

Kể cả khi kết quả cho ra đã tối ưu thì chứng minh một thuật toán tham lam tối
ưu là rất khó. Chứng minh một giải thuật tham lam là đúng là cả một nghệ thuật hơn là
một khoa học, vì nó đòi hỏi rất nhiều sự sáng tạo.

Nếu không cẩn thận bài toán sẽ rơi vào vòng lặp vô hạn => Không có lời giải
- Ví dụ bài toán:

Bài toán đếm số đồng tiền

Yêu cầu: Lựa chọn số lượng đồng tiền nhỏ nhất có thể sao cho tổng mệnh giá
của các đồng tiền này bằng với một lượng tiền cho trước.

TH1.
Tiền đồng có các mệnh giá:1, 2, 5, và 10 xu

Lượng tiền cho trước: 18 xu

Bước 1: Chọn đồng 10 xu, do đó sẽ còn 18 – 10 = 8 xu.


Bước 2: Chọn đồng 5 xu, do đó sẽ còn 8 – 5 = 3 xu.
Bước 3: Chọn đồng 2 xu, còn lại là 3 – 2 = 1 xu.
Bước 4: Cuối cùng chọn đồng 1 xu.

Kết quả: 10 + 5 + 2 + 1 = 4 đồng


Cách làm trên là khá ổn, và số lượng đồng tiền cần phải lựa chọn là 4 đồng tiền.
Nhưng chỉ cần thay đổi bài toán trên một chút thì cũng hướng tiếp cận như trên sẽ
không đem lại cùng kết quả tối ưu.

TH2.
Các đồng tiền có mệnh giá: 1, 7 và 10 xu

Lượng tiền cho trước: 15 xu

Kết quả theo thuật tham lam: 10 + 1 + 1 +1 + 1 + 1 = 6 đồng

Kết quả tối ưu: 7 + 7 + 1 = 3 đồng

Bài toán tô màu đồ thị


Yêu cầu: Cho trước một đồ thị, mỗi đỉnh có một giá trị ưu tiên gọi là “bậc”.
Thực hiện gán màu cho mỗi đỉnh của đồ thị sao cho hai đỉnh kề nhau không cùng một
màu, và số màu được sử dụng là ít nhất.

Input: đồ thị G = (V, E).


Output: đồ thị G = (V, E) có các đỉnh đã được gán màu.

Các bước của thuật toán:


Bước 1: Lập danh sách ưu tiên
Lập danh sách V’ = {v1, v2, ... , vn} là các đỉnh của đồ thị được sắp xếp theo
thứ tự bậc giảm dần: d(v1) > d(v2) > ... > d(vn).
Ban đầu tất cả các đỉnh trong V (V’) đều chưa được tô màu.
Gán i = 1.
Bước 2: Tô màu thứ i cho đỉnh đầu tiên trong danh sách V’. Duyệt lần lượt các
đỉnh khác trong V’ (nếu có) và chỉ tô màu i cho các đỉnh không kề đỉnh đã có màu i.
Bước 3: Kiểm tra
Nếu tất cả các đỉnh trong V’ đã được tô màu => Dừng thuật toán
=> Kết luận đồ thị đã sử dụng i màu để tô.
Ngược lại, chuyển sang bước 4.
Bước 4: Loại khỏi danh sách V’ các đỉnh đã tô màu.
Sắp xếp lại các đỉnh trong V’ theo thứ tự bậc giảm dần.
Gán i = i + 1 và quay lại bước 2.

Ví dụ
cụ thể như ở
dưới Bậc 3 Bậc 1

Bậc 2
Bậc 3

Bậc 1

Bước 1: Lập V’ ban đầu có thứ tự là [1, 5, 3, 2, 4].


Gán i =1.
Bước 2: Tô màu 1 (red) cho đỉnh 1.
Lần lượt duyệt các đỉnh còn lại trong V’:
Đỉnh 2, 3, 5 kề đỉnh 1 (đỉnh 1 đã tô màu 1 - red) => Bỏ qua
Đỉnh 4 không kề với đỉnh 1 => Tô màu 1 cho đỉnh 4.
Bước 3: Kiểm tra thấy vẫn còn các đỉnh [2, 3, 5] trong V chưa được tô màu
=> Tiếp tục
Bước 4: Loại bỏ các đỉnh 1, 4 đã được tô màu ra khỏi V’, sắp xếp lại V’ theo
thứ tự bậc giảm dần, ta thu được V’= [5, 3, 2].
Tăng i = 2. Thực hiện lặp lại bước 2:
Bước 2(1): Tô màu 2 (blue) cho đỉnh 5. Lần lượt duyệt các đỉnh còn lại trong
V’. Đỉnh 3 kề đỉnh 5, đỉnh 5 đã có màu => Bỏ qua
Đỉnh 2 không kề với đỉnh 5 => Tô màu 2 cho đỉnh 2.
Bước 3(1): Kiểm tra thấy vẫn còn đỉnh [3] chưa được tô màu
=> Tiếp tục
Bước 4(1): Loại bỏ các đỉnh 5, 2 đã được tô màu ra khỏi V’, V’=[3].
Tăng i = 3. Thực
hiện lặp lại bước 2:
Bước
2(2): Tô màu 3
(Green) cho đỉnh 3.
Bước 3(2): Kiểm tra thấy tất cả các đỉnh trong V đã được tô màu => Dừng

Kết luận: Đỉnh 1 và 4 được tô màu 1-red, đỉnh 5 và đỉnh 2 được tô màu 2-blue,
đỉnh 3 được tô màu 3-Green.
Số màu cần thiết phải sử dụng là i =3 màu.

A*

- Khái niệm: Thuật toán tìm đường đi trong đồ thị từ 1 điểm đến điểm đích, sử dụng
hàm heuristic ước lượng khoàng cách

- Tính chất:

+ Xây dựng đường đi tới đích bằng hàm heuristic đánh giá khoảng cách (có thể
là đánh giá bằng đường chim bay)

+ Từng quyết định chưa hoàn thành sẽ được lưu lại (không như thuật tham
lam), tránh xem xét các nhánh đã xác định đến thời điểm hiện tại có chi phí cao.

+ Có tính đầy đủ: Nếu bài toán có lời giải thì thuật toán chắc chắn tìm được 1
lời giải.

+ Có tính hiệu quả tối ưu với mọi hàm heuristic h (các thuật toán khác chỉ cần
mở rộng ít hơn A* chứ không phải sử dụng hàm h đó)

+ Không phải lúc nào cũng tối ưu. A* chỉ tối ưu khi:

- Tập ban đầu là tập đóng + Hàm heuristic thu nạp được
- Tập ban đầu không đóng + Hàm heuristic đơn điệu/nhất quán

- Nguyên lý:

Từng quyết định lựa chọn sẽ được lưu lại trong một hàng đợi (queue).

Thứ tự ưu tiên trong queue được quyết định bởi hàm tính chi phí

f ( x )=g ( x ) +h ( x )

g ( x ) = chi phí đường đi cho đến thời điểm hiện tại (tổng trọng số của các cạnh
đã đi qua)

h ( x ) = hàm đánh giá heuristic về chi phí nhỏ nhất để đến đích từ x

f ( x ) càng thấp, độ ưu tiên của x càng cao

Do đó có thể sử dụng một cấu trúc heap tối thiểu để cài đặt hàng đợi ưu tiên
này.

function A*(điểm_xuất_phát,đích)

var đóng:= tập rỗng

var q:= tạo_hàng_đợi(tạo_đường_đi(điểm_xuất_phát))

while q không phải tập rỗng

var p:= lấy_phần_tử_đầu_tiên(q)

var x:= nút cuối cùng của p

if x in đóng

continue

if x = đích

return p
bổ sung x vào tập đóng

foreach y in các_đường_đi_tiếp_theo(p)

đưa_vào_hàng_đợi(q, y)

return failure

Trong đó, các_đường_đi_tiếp_theo(p) trả về tập hợp các đường đi tạo bởi việc kéo
dài p thêm một nút kề cạnh. Giả thiết rằng hàng đợi được sắp xếp tự động bởi giá trị
của hàm f .

"Tập hợp đóng" (đóng) lưu giữ tất cả các nút cuối cùng của p (các nút mà các đường
đi mới đã được mở rộng tại đó) để tránh việc lặp lại các chu trình (việc này cho ra
thuật toán tìm kiếm theo đồ thị). Đôi khi hàng đợi được gọi một cách tương ứng là "tập
mở". Tập đóng có thể được bỏ qua (ta thu được thuật toán tìm kiếm theo cây) nếu ta
đảm bảo được rằng tồn tại một lời giải hoặc nếu hàm các_đường_đi_tiếp_theo được
chỉnh để loại bỏ các chu trình.

- Đánh giá

+ Ưu điểm

Thuật toán linh động, tổng quát

Thời gian tìm lời giải nhanh

+ Nhược điểm

Tốn nhiều bộ nhớ để lưu các trạng thái

- Ví dụ bài toán
Cơ bản:

Tìm đường đi ngắn nhất từ A đến K biết


khoảng cách giữa mỗi điểm ở hình bên
và khoảng cách đường chim bay được
cho như sau:

h(A) = 60 / h(B) = 53 / h(C) =


36 / h(D) = 35 / h(E) = 35 / h(F) =
19 / h(G) = 16 / h(H) = 38 / h(I) =
23 / h(J) = 0 / h(K) = 7

Sử dụng f(x) = h(x) + g(x) như


nguyên lý trên, ta được cây tìm kiếm:

64

Khi đó đường đi tối ưu là A – H – G – K với khoảng cách 15 + 3 + 7 = 22.

Nâng cao

Cho một bàn cờ với kích thước cho trước và 2 điểm 〇, △ nằm ở 2 vị trí bất kì.
Hãy tìm đường đi ngắn nhất từ 〇 đến △ biết rằng

 Các ô trắng là đường đi


 Các ô đen là vật cản, không đi được
 Tại một ô bất kỳ, chỉ có thể đi lên, xuông, trái, phải nếu không bị cản. Không
được đi chéo

Trong bài toán trên ta thấy rằng


đường đi ngắn nhất là đường chéo nối từ 〇 đến △

Tính chiều dài đường chéo áp dụng công thức Pythagoras:

h ( x )=√ a2 +b 2=√ 72 +52=8,6

Khi di chuyển qua mỗi ô thì giá trị của ô sẽ tăng lên 1 đơn vị => Xác định g(x)s

f ( x )=g ( x ) +h ( x ) nên ta có bảng như sau:


Tiếp theo từ vị trí 0 sẽ duyệt các ô lân cận nó để tìm ra đường ngắn nhất

B1. Xét điểm P(0,0)

Có 2 điểm liền kề P(1,0) và P(0,1)

f ( x )=g ( x ) +h ( x )=3,2 vì 2 giá trị bằng nhau nên chọn điểm nào cũng được.

B2. Giả dụ chọn điểm P(1,0)

Có 2 điểm liền kề: P ( 2,0 )=5,2 , P ( 1,1 )=4,8

Cộng với P(0,1) đang có sẵn thì ta có 3 điểm

P ( 0,1 )=3,4 ; P ( 2,0 )=5,4 ; P ( 1,1 )=4,8

P ( 2,0 )=5,4 là giá trị gần với giá trị 8.6 nhất => P(2,0) được chọn làm giá trị xét
tiếp theo.

Tương tự các bước trên ta được bảng như dưới.


Sau khi chạm được đến điểm △ thì ta được sơ đồ đường đi ngắn nhất như sau:

You might also like