Đây là một phương pháp thường dùng để giải quyết các bài toán tối ưucó cấu trúc phức tạp khó có thể giải được bằng phương pháp trực tiếp.. Nền tảng củaphương pháp này được xây dựng dựa t
Trang 1Đại học Công Nghệ Thông Tin Đại học Quốc gia Thành phố Hồ Chí Minh
BÁO CÁO:
PHƯƠNG PHÁP GIẢI TOÁN TRONG TIN HỌC:
QUY HOẠCH ĐỘNG
Môn học: PHƯƠNG PHÁP NGHIÊN CỨU KHOA HỌC
GVHD : GS.TSKH Hoàng Kiếm Học viên: Trần Ngọc Huy – CH1301027
TP.HCM, tháng 5 năm 2014
Trang 2Mục lục
1 Mở đầu 2
2 Khái niệm 2
3 Phương pháp phân tích bài toán quy hoạch động 3
4 Mô hình cài đặt 13
5 Tổng kết 17
Tài liệu tham khảo 17
Trang 31 Mở đầu
Để giải quyết một bài toán tối ưu trong tin học, ta có thể sử dụng nhiều cách khác nhau [3] Trong đó, phương pháp quy hoạch động được nhiều người quan tâm vì tính hiệu quả về mặt lưu trữ cũng như thời gian xử lý kết quả Về cơ bản, quy hoạch động chia nhỏ bài toán lớn về các bài toán con có phạm vi nhỏ hơn, tiếp tục như vậy đến khi bài toán nhỏ “đủ dễ” để có thể giải quyết Như vậy, việc tổng hợp lời giải từ các bài toán con là bước đi tìm lời giải cho bài toán lớn hơn Có thể nói quy hoạch động là phương pháp giải toán trong tin học ứng dụng nguyên lý sáng tạo “phân nhỏ” và “kết hợp” Nội dung được đề cập trong bài luận này là khái niệm cơ bản và phương pháp để giải một bài toán quy hoạch động, lần lượt được giới thiệu trong phần 2 và 3 Đồng thời giới thiệu hai cách tiếp cận bài toán quy hoạch động: một là cách tiếp cận bottom-up, hai là cách tiếp cận top-down trong phần 4 Cuối cùng, phần 5 sẽ tóm tắt nội dung toàn bộ bài luận
2 Khái niệm
Một trong các hướng giải quyết các bài toán tối ưu hóa trong tin học là ứng dụng quy hoạch động Đây là một phương pháp thường dùng để giải quyết các bài toán tối ưu
có cấu trúc phức tạp (khó có thể giải được bằng phương pháp trực tiếp) Nền tảng của phương pháp này được xây dựng dựa trên nguyên lý tối ưu của Richard Bellman (Bellman’s Principle of Optimality, 1940) :
“Nếu một dãy các lựa chọn là tối ưu thì mọi dãy con của nó cũng tối ưu”
Bản chất của quy hoạch động là chia để trị [1, 4] Thế nên, nhiều bài toán phức tạp trong thực tế không thể dễ dàng tìm được lời giải tối ưu một cách trực tiếp (dưới dạng một công thức toán học tường minh), mà phải biểu diễn lời giải tối ưu đó của một bài toán lớn dưới dạng tổ hợp các lời giải tối ưu, được thể hiện qua công thức truy hồi, của các bài toán con đơn giản hơn Như vậy, việc tìm lời giải cho bài toán lớn là quá trình tìm
Trang 4lời giải cho các bài toán con có phạm vi nhỏ hơn Tương tự, các bài toán con này cũng được chia ra thành các bài toán con nhỏ hơn nữa, đến khi “đủ dễ” có thể cho lời giải trực tiếp Quá trình này áp dụng nguyên lý “phân nhỏ” bài toán Khi đã có lời giải cho tất cả các bài toán con, chúng ta sẽ tổng hợp các lời giải này theo công thức truy hồi đã xác định để xây dựng lời giải cho bài toán lớn Nguyên lý sáng tạo được sử dụng ở giai đoạn này là nguyên lý “kết hợp”
3 Phương pháp phân tích bài toán quy hoạch động
Một bài toán tối ưu bằng quy hoạch động được giải quyết dựa trên cấu trúc tối ưu của nó [4] Cấu trúc tối ưu, hay còn gọi là công thức quy hoạch động, chính là cách biểu diễn một bài toán lớn dưới dạng tổ hợp của các bài toán con Để chỉ ra được cấu trúc tối ưu của bài toán, chúng ta cần phải xác định tập các trạng thái biểu diễn của bài toán và các bài toán con của nó, hay nói cho chính xác là chúng ta phải xác định không gian của bài toán
Việc xác định không gian biểu diễn cho bài toán có thể nói là vấn đề cốt lõi của quy hoạch động Đó là công đoạn khó nhất, đòi hỏi kinh nghiệm và tính sáng tạo rất cao Xác định trạng thái biểu diễn như thế nào cho hợp lý và hiệu quả chính là nghệ thuật giải quyết vấn đề Cụ thể, khi giải một bài toán F, chúng ta cần xác định họ bài toán con F[w] với w là một vector tham số sao cho khi thay w = w0 thì ta thu được bài toán ban đầu F = F[w0] Các tiêu chí tối thiểu để đánh giá tính khả thi cho không gian biểu diễn của bài toán là :
Tồn tại cấu trúc tối ưu giữa các bài toán
Kích thước của không gian các bài toán phải đủ nhỏ để có thể lưu trữ trong quá trình xử lý
Trang 5Để xác định cấu trúc tối ưu cho không gian F[w] của các bài toán, ta cần phải xây dựng một hệ thức truy toán (công thức quy hoạch động) biểu diễn mối liên quan giữa một bài toán bất kỳ F[w] với các bài toán liên quan có kích thước nhỏ hơn :
F[w] = Q{F[w’], F[w’’], …} (*) Việc tìm công thức, phương trình truy toán hoặc tìm cách phân rã bài toán để xây dựng cấu trúc tối ưu nhiều khi đòi hỏi sự phân tích tổng hợp rất công phu, dễ sai sót, khó nhận ra như thế nào là thích hợp, đòi hỏi rất nhiều thời gian suy nghĩ
Một điểm cần lưu ý nữa khi ta xác định không gian biểu diễn cho bài toán (hay còn gọi là trạng thái quy hoạch động) là đồ thị biểu diễn sự chuyển tiếp giữa các trạng thái quy hoạch động phải là đồ thị có hướng không chu trình Nói cho đơn giản, giả sử
đồ thị biểu diễn đó tồn tại một chu trình A1, A2, …, AN, A1 thì khi tính giá trị cho hàm quy hoạch động tại A1 ta sẽ dựa trên A2 và A2 lại dựa trên A3 … và cuối cùng thì khi tính AN ta lại phải dựa trên A1 trong khi giá trị tại A1 chính là cái chúng ta đang tìm !
Để có thể hiểu rõ hơn về bản chất của phương pháp quy hoạch động, chúng ta xem xét những ví dụ sau :
Ví dụ 1 : Xét trò chơi gồm một bảng kích thước N * N (N ¿ 100), trên mỗi ô của bảng được quy định một điểm số nhất định Ban đầu, người chơi xuất phát tại một ô bất kỳ nằm trên cột đầu tiên bên trái của bảng Mỗi khi đi tới một ô trên bảng thì người chơi sẽ được thưởng số điểm quy định cho ô đó Tại mỗi nước đi, người chơi bắt buộc phải di chuyển qua cột tiếp theo bên phải nhưng được quyền chọn một trong
ba hướng : đi chéo lên, đi thẳng hay đi chéo xuống Hỏi nếu người chơi đi tối ưu thì tổng số điểm thưởng anh ta thu được là bao nhiêu ?
Trang 6Giải pháp : Gọi A[x, y] là điểm số quy định cho ô (x, y) và F[x, y] là điểm số tối đa
mà người chơi thu được để đi tới ô (x, y) Như thế, điểm số tối đa mà người chơi có
thể thu được là maxx=1 N F[x, N]
Ở đây, dễ thấy là khi ta đưa ra định nghĩa cho F[x, y] như trên cũng tức là ta đã khẳng định cách lựa chọn đối với không gian của bài toán Việc tiếp theo chúng ta cần làm là xác định cấu trúc tối ưu của bài toán Trước hết, chúng ta có nhận xét là để đến được ô (x, y) thì trước đó người chơi phải đứng ở một trong các ô trước đó (x – 1, y – 1), (x, y – 1), (x + 1, y – 1) Như thế, chúng ta có 3 lựa chọn khi tính giá trị F[x, y] :
F[x, y] = F[x – 1, y – 1] + A[x, y]
F[x, y] = F[x – 1, y] + A[x, y]
F[x, y] = F[x – 1, y + 1] + A[x, y]
Trang 7Khi đó, để tối ưu hóa F[x, y] ta chỉ đơn giản là lấy giá trị tối ưu trong số các giá trị ứng với các lựa chọn nói trên :
F[x, y] = max{F[x – 1, y – 1], F[x, y – 1], F[x + 1, y – 1]} + A[x, y]
Cuối cùng, chúng ta cần xác định khi nào bài toán F[x, y] là đủ “nhỏ” để giải quyết một cách trực tiếp : ∀ x và y = 1 : F[x, y] = A[x, y]
Qua ví dụ này, chúng ta có thể rút ra nhận xét sau : Bản chất của phương pháp quy hoạch động là nhằm xác định một chuỗi các chuyển tiếp với chi phí tối ưu từ các trạng thái khởi đầu, ứng với các bài toán đủ “nhỏ” để giải trực tiếp, qua một số trạng thái trung gian, ứng với các bài toán con trung gian, và đến trạng thái đích, ứng với bài toán lớn cần giải
Ví dụ 2 : Xét bảng kích thước M * N (M, N ¿ 100) với một con cờ đặt ở ô trên trái của bảng Tại mỗi nước đi, con cờ chỉ có thể đi thẳng xuống hay đi sang phải một ô Hỏi có bao nhiêu cách di chuyển khác nhau để con cờ di chuyển từ vị trí ban đầu đến
ô phải dưới của bàn cờ
Giải pháp : Bài toán nêu ra trong ví dụ này về bản chất là một bài toán đếm chứ
không phải một bài toán tối ưu Tuy nhiên, đối với các dạng bài toán đếm như vậy chúng ta vẫn có thể áp dụng được nguyên tắc “chia để trị” : Thay vì tìm công thức tính trực tiếp, chúng ta xây dựng công thức truy hồi biểu diễn hàm giá trị (đáp số) của bài toán lớn dưới dạng tổ hợp các hàm giá trị của các bài toán con có quy mô nhỏ hơn
Trang 8Ta có nhận xét, để đến được một ô (x, y) bất kỳ trên bảng thì trước đó con cờ phải
ở một trong hai ô (x – 1, y) và (x, y – 1) Như vậy, tương tự như ở ví dụ trên, chúng ta
có hai trường hợp :
Nếu trước khi đến ô (x, y) ta ràng buộc là con cờ phải đến ô (x – 1, y) trước thì ta
có tất cả F[x – 1, y] cách di chuyển khác nhau để đến ô (x, y)
Tương tự, nếu ràng buộc con cờ phải đến ô (x, y – 1) trước khi đến (x, y) thì ta có tất cả F[x, y – 1] cách di chuyển khác nhau
Khi đó, để xác định F[x, y] ta lấy tổng các cách đi khác nhau của hai trường hợp nói trên : F[x, y] = F[x – 1, y] + F[x, y – 1] Cuối cùng, vấn đề còn lại là xác định “lời giải” cho các bài toán đủ “nhỏ” :
F[1, 1] = 1
F[1, x] = 1 (x > 1)
F[x, 1] = 1 (x > 1)
Ví dụ 3 : Xét ma trận M * N trong đó mỗi ô của ma trận chứa một số nguyên dương
bất kỳ Ban đầu một con cờ được đặt ở ô (x0, y0) và nó cần phải được di chuyển tới ô (x1, y1) sau tối đa K bước Tại mỗi bước con cờ chỉ có thể di chuyển qua một trong bốn ô xung quanh Chi phí của một bước đi được xác định bằng độ chênh lệch giữa hai số thuộc ô đầu và ô đích của bước đi đó Hãy xác định chi phí tối thiểu để đưa con
cờ về ô (x1, y1)
Giải pháp : Để xây dựng không gian trạng thái quy hoạch động, ta định nghĩa lớp bài
toán con sau đây :
“Hãy xác định chi phí tối thiểu để đưa con cờ từ ô (x 0 , y 0 ) về ô (x, y) trong đúng z
bước”
Trang 9Dễ thấy trạng thái biểu diễn cho một bài toán con thuộc lớp bài toán nói trên là một bộ ba (x, y, z) Ta gọi F[x, y, z] là lời giải cho bài toán tương ứng Như vậy, khi
ta thay x = x1, y = y1 thì lời giải cho bài toán lớn ban đầu là maxz=0 K F[ x1, y1,z ]
Để tính F[x, y, z] thì ta có xét bốn vị trí có thể có của con cờ ngay trước khi di chuyển đến ô (x, y) ở nước đi z : (x – 1, y), (x, y – 1), (x + 1, y) và (x, y + 1) Khi đó, công thức quy hoạch động tính F[x, y, z] có thể được viết như sau :
F[x, y, z] = max{F[x – 1, y, z – 1] + |A[x, y] – A[x – 1, y]|,
F[x, y – 1, z – 1] + |A[x, y] – A[x, y – 1]|,
F[x + 1, y, z – 1] + |A[x, y] – A[x + 1, y]|,
F[x, y + 1, z – 1] + |A[x, y] – A[x, y + 1]|}
Khi đặt z = 0, ta được lớp các bài toán con đủ “nhỏ” để có thể giải trực tiếp :
F[x0, y0, 0] = 0
F[x, y, 0] = +oo (xem như không thể đến được)
Ví dụ 4 : Cho hai chuỗi A1A2…AM và B1B2…BN (M, N ¿ 200) Hãy tìm dãy con chung (không nhất thiết phải liên tiếp) dài nhất của hai chuỗi trên
Giải pháp : Ta xây dựng không gian quy hoạch động qua việc định nghĩa lớp bài toán
con sau :
Trang 10“Xác định dãy con chung dài nhất của hai chuỗi A 1 A 2 …A i và B 1 B 2 …B j ”
Khi đó, trạng thái biểu diễn cho một bài toán con thuộc lớp này là một cặp (i, j)
Ta định nghĩa F[i, j] là lời giải của bài toán tương ứng Như vậy, khi ta thay i = M và j
= N thì F[M, N] chính là lời giải của bài toán lớn ban đầu Vấn đề còn lại là xác định cấu trúc tối ưu cho F[i, j]
Ta xét hai trường hợp sau :
A[i] = B[j] : Trong trường hợp này, dễ thấy là tồn tại ít nhất một dãy con chung dài nhất của Ai và Bj sao cho ký tự cuối x = A[i] = B[j] Ở trường hợp này, rõ ràng F[i, j] = F[i – 1, j – 1] + 1
A[i] ¿ B[j] : Lúc này lại có hai khả năng có thể xảy ra là A[i] không thuộc dãy con chung dài nhất hay B[j] không thuộc dãy con chung dài nhất Ở trường hợp này, F[i, j] sẽ có giá trị tương ứng là F[i – 1, j] hay F[i, j – 1] tùy theo việc ta chọn A[i] hay B[j] thuộc dãy con chung dài nhất Tất nhiên, để tối ưu hóa giá trị của F[i, j] ta sẽ luôn chọn trường hợp tốt nhất : F[i, j] = max { F[i – 1, j], F[i, j – 1] }
Cuối cùng, ta giải trực tiếp các bài toán con đủ “nhỏ” : F[i, 0] = 0 và F[0, j] = 0
Ví dụ 5 : Cho một valy có thể chứa W ¿ 10000 đơn vị trọng lượng Có N ¿ 200 loại đồ vật (số lượng mỗi đồ vật không hạn chế) Đồ vật i có trọng lượng A[i] và giá trị là C[i] Hỏi nên chọn mỗi loại đồ vật bao nhiêu để xếp vào valy để tổng giá trị hàng hóa trong valy là lớn nhất ?
Trang 11Giải pháp : Để xây dựng không gian quy hoạch động cho bài toán, ta định nghĩa họ
bài toán sau đây :
“Xác định xem với một valy có thể chứa x đơn vị trọng lượng và y loại đồ vật từ
1 đến y trong số N loại đồ vật nói trên thì ta có thể chất đồ vào valy để đạt tổng
giá trị hàng hóa lớn nhất là bao nhiêu ?”
Trạng thái quy hoạch động cho các bài toán trên được biểu diễn dưới dạng một cặp tham số (x, y) Gọi F[x, y] là lời giải tối ưu cho bài toán tương ứng, ta sẽ lập hệ thức truy toán cho F[x, y] như sau :
Nếu ta quyết định bỏ đồ vật loại y vào trong valy (chỉ xét khi A[y] ¿ x) thì ta có thể tính F[x, y] = F[x – A[y], y] + C[y]
Nếu ta quyết định không bỏ thêm bất cứ đồ vật loại y nào vào trong valy nữa thì F[x, y] = F[x, y – 1]
Như vậy, ta một thời điểm bất kỳ khi tính F[x, y] ta cần chọn quyết định tối ưu để cực đại hóa giá trị của F[x, y] : F[x, y] = max { F[x – A[y], y] + C[y], F[x, y – 1] }
Cuối cùng, ta tiến hành giải các bài toán con đủ “dễ” để làm trực tiếp :
F[x, 1] = C[1] * (x / A[1])
F[0, x] = 0
Ví dụ 6 : Lan có N bình hoa và N bó hoa (N ¿ 16) Một bình hoa và một bó hoa bất
kỳ có thể hợp nhau mà cũng có thể không hợp nhau Sự hợp nhau giữa bình hoa và bó hoa được biểu diễn thông qua ma trận N * N :
Trang 12 A[x, y] = 1 khi và chỉ khi bình hoa thứ x hợp với bó hoa thứ y.
A[x, y] = 0 trong trường hợp ngược lại
Hỏi Lan có tất cả bao nhiêu cách ghép cặp các bó hoa với các bình hoa Một cách ghép cặp ở đây được hiểu là một cách sắp xếp các bình hoa và bó hóa thành N cặp sao cho với mọi cặp (x, y) ta có A[x, y] = 1
Giải pháp : Trong ví dụ này ta lại xét một bài toán đếm khác Cũng giống như ví dụ ở
trên, bài toán này có thể được giải bằng phương pháp quy hoạch động nhưng việc xác định trạng thái bài toán con lại phức tạp hơn rất nhiều
Cụ thể, ta định nghĩa lớp bài toán con sau đây :
“Đếm xem có bao nhiêu cách ghép cặp X bình hoa từ 1 đến X với một tập con gồm X bó hoa bất kỳ của tập N bó hoa ban đầu.”
Dễ thấy khi cho X = N, ta thu được bài toán đếm ban đầu Để áp dụng quy hoạch động cho bài toán này, ta cần mô hình hóa lớp các bài toán con nói trên dưới dạng tập các trạng thái Cụ thể, với mỗi bài toán con ta biểu diễn nó dưới dạng một trạng thái nào đấy
Đầu tiên, ta thấy tham số của một bài toán con bất kỳ gồm một cặp (X, S) trong đó
S là một tập con có X phần tử của tập {1, 2, …, N} Vấn đề đặt ra bây giờ là làm sao biểu diễn cặp (X, S) một cách hiệu quả ? Ta có hai nhận xét sau đây :
Trang 13 Thứ nhất, ta biết rằng X = |S| do vậy khi lưu trữ trạng thái của bài toán con (X, S)
ta chỉ cần lưu S
Thứ hai, S là một tập con của tập {1, 2, …, N} với N cố định nên dễ thấy là để lưu trữ S ta cần N bit (bit thứ x bằng 1 ứng với việc x ¿ S và ngược lại)
Từ hai nhận xét trên ta thấy trạng thái của bài toán con (X, S) có thể được biểu diễn trên máy tính dưới dạng một số nguyên N bit, trong đó có X bit 1 Như vậy, không gian bài toán con của ta sẽ có kích thước 2N và với N ¿ 16 thì kích thước đó hoàn toàn thích hợp cho việc lưu trữ
Ở bước tiếp theo, ta cần xây dựng cấu trúc tối ưu / hàm quy hoạch động cho không gian bài toán nói trên Để dễ hình dung, ta gọi Q(S) là giá trị của số nguyên N bit biểu diễn cho bài toán con (X, S) và định nghĩa F[Q(S)] là số cách ghép tương ứng Ta xét các bó hoa T có khả năng ghép với bình hoa X :
A[X, T] = A[T, X] = 1
Q(S) & 2T = 2T (bit thứ T của Q(S) có giá trị bằng 1)
Nếu ta chọn ghép X với T, thì khi đó số cách ghép cho X – 1 bình hoa với tập hợp
S – {T} bó hoa còn lại là F[Q(S – {T})] = F[Q(S) – 2T] Từ đó, ta rút ra công thức tính
F[Q(S)] như sau : F[Q(S)] = ∑
T F[Q(S) – 2T]
Để rút ra đáp số cho bài toán đếm ban đầu, ta thay X = N : F[Q(S)] = F[2N – 1]
Lưu ý : Trong trường hợp này, các bài toán đủ “nhỏ” để có thể giải trực tiếp chính
là các bài toán (X, S) với X = |S| = 1