Tác giả luận văn Trang 3 iii LỜI CẢM ƠN Trong thời gian thực hiện đề tài "Một số thuật toán xấp xỉ và ứng dụng cho bài tốn lập lịch" tơi đã nhận được sự quan tâm, giúp đỡ của các thầy
Trang 1ĐẠI HỌC THÁI NGUYÊN TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN VÀ TRUYỀN
LUẬN VĂN THẠC SĨ KHOA HỌC MÁY TÍNH
Người hướng dẫn khoa học:
1 TS Vũ Vinh Quang
2 TS Hoàng Thị Mai
Thái Nguyên, tháng 8 năm 2023
Trang 2ii
LỜI CAM ĐOAN
Tôi xin cam đoan rằng, đây là công trình nghiên cứu của riêng tôi Tất cả các nguồn số liệu và kết quả nghiên cứu trong luận văn này là trung thực và chưa được
sử dụng để bảo vệ một học vị nào Các thông tin trích dẫn trong luận văn đều đã được chỉ rõ nguồn gốc
Tác giả luận văn
Bùi Ánh Dương
Trang 3Tôi xin trân trọng cảm ơn Trường Đại học Công nghệ thông tin và Truyền thông Thái Nguyên, Phòng Sau đại học đã tạo điều kiện cho tôi trong thời gian học tập, nghiên cứu và hoàn thành chương trình học tập của khóa học
Tôi xin chân thành cảm ơn các đồng chí lãnh đạo, các cán bộ, giảng viên trường Đại học Thủ đô Hà Nội và trường Đại học Công nghệ Thông tin và Truyền thông Thái Nguyên đã giúp đỡ, tạo điều kiện về thời gian cho tôi đi học cao học và cung cấp tài liệu cho tôi trong quá trình nghiên cứu đề tài
Đồng thời tôi xin chân thành cảm ơn tập thể anh, chị, em lớp thạc sĩ Khoa học máy tính khóa 20 đã giúp đỡ tôi rất nhiều trong thời gian học tập, nghiên cứu và hoàn thành luận văn
Mặc dù đã có nhiều cố gắng, song luận văn không thể tránh khỏi những thiếu sót Do vậy tôi mong nhận được sự góp ý của các thầy giáo, cô giáo và các bạn để luận văn được hoàn thiện hơn
Tôi xin chân thành cảm ơn!
Tác giả luận văn
Bùi Ánh Dương
Trang 4iv
DANH MỤC VIẾT TẮT
2 NPC Tính đầy đủ của đa thức không xác định
Trang 5v
MỤC LỤC
LỜI CAM ĐOAN ii
LỜI CẢM ƠN iii
DANH MỤC VIẾT TẮT iv
MỤC LỤC v
DANH MỤC CÁC BẢNG vii
MỞ ĐẦU 1
CHƯƠNG 1 MỘT SỐ KIẾN THỨC CƠ BẢN 4
1.1 Khái niệm cơ bản về thuật toán, độ phức tạp của thuật toán 4
1.1.1 Thuật toán 4
1.1.2 Độ phức tạp của thuật toán 5
1.1.3 Vấn đề phân lớp các bài toán 8
1.2 Mô hình bài toán tối ưu rời rạc 8
1.2.1 Định nghĩa 8
1.2.2 Chú ý 9
1.3 Một số bài toán kinh điển 10
1.3.1 Bài toán vận tải 10
1.3.2 Bài toán phân việc 11
1.3.3 Bài toán cái túi 11
1.3.4 Bài toán xếp hàng lên tàu 12
1.3.5 Bài toán Knapsack 13
1.3.6 Bài toán Knapsack mở rộng 15
CHƯƠNG 2 MỘT SỐ THUẬT TOÁN XẤP XỈ 19
2.1 Khái niệm về thuật toán xấp xỉ 19
2.2 Các thuật toán tìm kiếm đường đi ngắn nhất trên mô hình đồ thị 20
2.2.1 Thuật toán Dijkstra 20
2.2.2 Thuật toán Floyd 23
Trang 6vi
2.3 Một số thuật toán xấp xỉ sử dụng kỹ thuật Quy hoạch động và tham lam
25
2.3.1 Phương pháp quy hoạch động 25
2.3.2 Phương pháp tham lam 29
CHƯƠNG 3 MỘT SỐ ỨNG DỤNG 41
3.1 Mô hình tối ưu hóa điều chuyển hàng hóa trên đồ thị 41
3.1.1 Đặt bài toán 41
3.1.2 Đề xuất thuật toán 42
3.1.3 Một số kết quả thực nghiệm 43
3.2 Mô hình lập lịch thi tối ưu 48
3.2.1 Đặt vấn đề 48
3.2.2 Giới thiệu tổng quan Trường Đại học Thủ đô Hà Nội 49
3.2.3 Mô hình và hiện trạng lập lịch tại nhà trường 50
3.2.4 Đề xuất mô hình 51
3.2.5 Đề xuất thuật toán xấp xỉ 53
3.2.6 Một số kết quả thực nghiệm 63
KẾT LUẬN 79
TÀI LIỆU THAM KHẢO 80
PHỤ LỤC: Các chương trình nguồn liên quan đến bài toán thực tế 81
Trang 7vii
DANH MỤC CÁC BẢNG
1 Ví dụ về tìm đường đi ngắn nhất (2.2.1 Thuật toán Dijkstra)
2 Bảng phương án (2.3.1.2 Các bước tiến hành)
3 Bảng MA_KHOA (3.2.4 Đề xuất mô hình)
4 Bảng MA_LOP (3.2.4 Đề xuất mô hình)
5 Bảng MA_MON (3.2.4 Đề xuất mô hình)
6 Bảng tổ hợp Khoa - Lớp - Môn (3.2.4 Đề xuất mô hình)
7 Bảng Lịch thi (3.2.4 Đề xuất mô hình)
8 Bảng LICH_KHOA (3.2.4 Đề xuất mô hình)
9 Bảng LICH_LOP (3.2.4 Đề xuất mô hình)
10 Bảng LICH_MON (3.2.4 Đề xuất mô hình)
11 Bảng CB1 (3.2.4 Đề xuất mô hình)
12 Bảng SS_1 (3.2.4 Đề xuất mô hình)
Trang 8Hầu hết các bài toán tối ưu rời rạc đều là các bài toán thuộc lớp NP hoặc NPC [9][10] và một phương pháp luôn tìm được lời giải đúng của bài toán tối ưu chính là phương pháp liệt kê mọi phương án của bài toán từ đó chỉ ra phương án tối ưu Tuy nhiên độ phức tạp của thuật toán này là O(n!) với n là kích thước đầu vào của dữ liệu, do đó thông thường người ta thường xây dựng hướng tiếp cận tìm nghiệm gần tối ưu bằng các thuật toán xấp xỉ [6][7][8]
Nội dung chính của luận văn đề xuất việc nghiên cứu mô hình tối ưu rời rạc và một số thuật toán xấp xỉ tìm nghiệm gần tối ưu, từ đó tiến hành xây dựng mô hình lập lịch điều chuyển hàng hóa tối ưu trên đồ thị và mô hình bài toán lập lịch thi trong trường đại học, cài đặt và chạy thử nghiệm thuật toán trên máy tính điện tử, đánh giá hiệu quả của các thuật toán Vì vậy, tác giả luận văn đã chọn đề tài "Một
số thuật toán xấp xỉ và ứng dụng cho bài toán lập lịch" làm đề tài luận văn của mình
2 Đối tượng và phạm vi nghiên cứu
a Đối tượng nghiên cứu
- Lý thuyết về thuật toán và độ phức tạp của thuật toán
- Mô hình tối ưu rời rạc tổng quát
- Khái niệm về thuật toán xấp xỉ
- Mô hình tối ưu vận chuyển hàng hóa, lập lịch thi trong trường Đại học
b Phạm vi nghiên cứu
Trang 92
- Tìm hiểu lý thuyết về độ phức tạp thuật toán, vấn đề phân lớp các bài toán
- Mô hình tối ưu hóa rời rạc, một số bài toán kinh điển
- Mô hình tối ưu vận chuyển hàng trên đồ thị
- Mô hình lập lịch thi trong trường Đại học
- Cài đặt thuật toán mô phỏng
3 Hướng nghiên cứu
+ Nghiên cứu lý thuyết: Nghiên cứu tổng quan lý thuyết về mô hình tối ưu rời rạc, một số thuật toán xấp xỉ tìm nghiệm gần tối ưu Nghiên cứu hai mô hình vận chuyển hàng và lập lịch thi trong trường Đại học
+ Nghiên cứu thực nghiệm:
- Tìm hiểu ngôn ngữ lập trình C++ tiến hành cài đặt thử nghiệm các thuật toán xấp xỉ đối với một số bài toán tối ưu rời rạc kinh điển
- Xây dựng mô hình tối ưu vận chuyển hàng và mô hình lập lịch thi trong trường Đại học, cài đặt các thuật toán Đánh giá kết quả ứng dụng
4 Phương pháp nghiên cứu
- Phương pháp nghiên cứu lý thuyết: Tìm hiểu, thu thập tài liệu có liên quan
đến mô hình tối ưu rời rạc, một số lời giải tối ưu Nghiên cứu các thuật toán xấp xỉ tìm nghiệm gần tối ưu đối với bài toán tối ưu rời rạc
- Phương pháp nghiên cứu thực nghiệm: Cài đặt thử nghiệm các thuật toán
trên ngôn ngữ C++ Xây dựng chương trình tìm nghiệm gần tối ưu đối với mô hình điều phối vận chuyển hàng và mô hình lập lịch Cài đặt các chương trình và đánh giá kết quả
5 Ý nghĩa khoa học và thực tiễn
- Ý nghĩa khoa học: Nghiên cứu mô hình tối ưu rời rạc tổng quát, một số thuật
toán xấp xỉ giải quyết mô hình Xây dựng ứng dụng mô hình vận chuyển hàng và lập lịch tối ưu trong trường Đại học
Trang 103
- Ý nghĩa thực tiễn: Từ các kết quả nghiên cứu cho thấy ý nghĩa quan trọng của
mô hình tối ưu rời rạc và các thuật toán xấp xỉ đối với các bài toán tối ưu trong thực
tế
6 Nội dung nghiên cứu
Ngoài phần Mở đầu, Kết luận, Tài liệu tham khảo, luận văn được kết cấu thành
3 chương như sau:
Chương 1: Một số kiến thức cơ bản
Chương 2: Một số thuật toán xấp xỉ
Chương 3: Một số ứng dụng
Phần phụ lục: Các chương trình nguồn
Trang 114
CHƯƠNG 1 MỘT SỐ KIẾN THỨC CƠ BẢN 1.1 Khái niệm cơ bản về thuật toán, độ phức tạp của thuật toán
1.1.1 Thuật toán
1.1.1.1 Khái niệm bài toán
Một bài toán trong tin học là một bài toán thỏa mãn: xuất phát từ bộ dữ liệu đầu vào (Input), chúng ta phải thu được bộ Output đầu ra
Một số vấn đề cần quan tâm:
+ Bài toán được giải bằng máy tính điện tử
+ Cần làm rõ: dữ liệu cần được đưa vào máy tính (Input) là gì và cần trả lại (Output) thông tin gì?
+ Làm thế nào để từ Input ta có được Output? (Thuật toán)
Hiển nhiên đối với bài toán tin học là nghiên cứu thuật toán giải bài toán tương ứng
1.1.1.2 Khái niệm thuật toán
Định nghĩa: Thuật toán là một dãy hữu hạn các thao tác được sắp xếp theo một
trình tự nhất định để sau khi thực hiện dãy các thao tác đó, từ input ta có output cần tìm.[1]
Trong lý thuyết thuật toán, cụm từ "giải thuật" còn được gọi là "thuật toán"
1.1.1.3 Các yêu cầu của thuật toán
Thuật toán phải đảm bảo các yêu cầu dưới đây:
- Tính tổng quát: thuật toán cần phải áp dụng được cho mọi bài toán có cùng dạng mong muốn, chứ không phải chỉ cho một tập đặc biệt dữ liệu đầu vào
- Tính xác định: Các bước của thuật toán phải được trình bày rõ ràng, mạch lạc, đảm bảo cho người đọc chỉ hiểu theo một nghĩa duy nhất
- Tính khả thi: Thuật toán phải thực hiện được, nghĩa là ta có thể sử dụng máy tính kết hợp giữa các ngôn ngữ lập trình để thể hiện thuật toán trong thời gian hữu hạn
- Tính dừng: Nếu dữ liệu vào thỏa mãn điều kiện đầu vào thì thuật toán phải kết thúc và cho ra kết quả sau một số hữu hạn bước
Trang 121.1.1.4 Các phương pháp mô tả thuật toán
Thuật toán được thể hiện bằng một trong các cách sau:
• Phương pháp liệt kê:
Liệt kê lần lượt các bước để thực hiện thuật toán, tại mỗi bước ta sử dụng các
ký hiệu toán học kết hợp với ngôn ngữ tự nhiên
• Phương pháp sơ đồ khối:
Sử dụng ba loại hình khối để thể hiện là: hình elip chỉ điểm bắt đầu hay kết thúc, hình thoi chỉ khối kiểm tra và hình chữ nhật chỉ khối tính toán Có một cung định hướng để chỉ hướng đi của thuật toán
• Mô tả thuật toán bằng các chương trình
Sử dụng ngôn ngữ lập trình để thể hiện thuật toán, cấu trúc chặt chẽ của ngôn ngữ lập trình cho phép chúng ta thể hiện thuật toán một cách rõ ràng và dễ hiểu
1.1.2 Độ phức tạp của thuật toán
1.1.2.1 Chi phí phải trả cho một quá trình tính toán
Xét một quá trình tính toán, chi phí phải trả cho một quá trình tính toán bao gồm:
+ Chi phí về không gian: bộ nhớ - số ô nhớ cần sử dụng trong quá trình tính toán + Chi phí về thời gian: thời gian cần sử dụng cho một quá trình tính toán
Cho một thuật toán A Thuật toán này thực hiện trên bộ dữ liệu e Khi đó thuật toán
A phải trả 2 giá: giá về không gian là 𝐿𝐴(𝑒), giá về thời gian là 𝑇𝐴(𝑒), e là bộ dữ liệu vào
Nhận xét: cùng một thuật toán A mà xác định thực hiện trên các bộ dữ liệu khác
nhau sẽ trả các giá khác nhau Khi đó ta có các khái niệm về chi phí phải trả trong các trường hợp như sau:
Trang 13Nhận xét: Ngày nay do sự phát triển không ngừng của khoa học công nghệ kỹ thuật
điện tử nên chi phí về bộ nhớ không còn là vấn đề cần thiết phải bàn tới mà ta chỉ quan tâm tới chi phí phải trả về thời gian thực hiện thuật toán Từ đây ta chỉ xét đến thời gian thực hiện thuật toán 𝑇(𝑛), hay đó chính là độ phức tạp của thuật toán 1.1.2.2 Thời gian thực hiện thuật toán
Với một bài toán, không chỉ có một thuật toán Chọn một thuật toán đưa tới kết quả nhanh là một đòi hỏi thực tế Nhưng căn cứ vào đâu để có thể nói được thuật toán này nhanh hơn thuật toán kia?
Có thể thấy ngay: thời gian thực hiện một thuật toán phụ thuộc vào rất nhiều
yếu tố Một yếu tố cần chú ý trước tiên đó là kích thước của dữ liệu vào Chẳng hạn
thời gian sắp xếp một dãy số phải chịu ảnh hưởng của số lượng các số thuộc dãy số
đó Nếu gọi n là số lượng này (kích thước của dữ liệu vào) thì thời gian thực hiện T của một thuật toán phải được biểu diễn như một hàm của n: 𝑇(𝑛)
Các kiểu lệnh và tốc độ xử lý của máy tính, ngôn ngữ viết và chương trình dịch ngôn ngữ ấy đều ảnh hưởng tới thời gian thực hiện; nhưng những yếu tố này không đồng đều với mọi loại máy trên đó để cài đặt thuật toán, vì vậy không thể đưa chúng vào khi xác lập 𝑇(𝑛) Điều đó có nghĩa là 𝑇(𝑛) không thể được biểu diễn thành đơn vị thời gian bằng giây, bằng phút được Tuy nhiên, không phải vì thế
mà không thể so sánh được các thuật toán về mặt tốc độ Nếu như thời gian thực hiện của một thuật toán là 𝑇1(𝑛) = 𝑐 𝑛2 và thời gian thực hiện một thuật toán khác
là 𝑇2(𝑛) = 𝑘 𝑛 (với c và k là một hằng số nào đó), thì khi n khá lớn, thời gian thực hiện thuật toán 𝑇2 rõ ràng ít hơn so với thời gian thực hiện thuật toán 𝑇1 Như vậy, nếu nói thời gian thực hiện thuật toán bằng 𝑇(𝑛) tỉ lệ với 𝑛2 hay tỉ lệ với n cũng cho
Trang 147
ta ý niệm về tốc độ thực hiện thuật toán đó khi n khá lớn (với n nhỏ thì việc xét 𝑇(𝑛) không có ý nghĩa) Cách đánh giá thời gian thực hiện thuật toán độc lập với máy tính và các yếu tố liên quan với máy như vậy sẽ dẫn tới khái niệm về cấp độ lớn của thời gian thực hiện thuật toán hay còn gọi là độ phức tạp tính toán của thuật toán
1.1.2.3 Độ phức tạp của thuật toán
Định nghĩa: Một hàm 𝑓(𝑛) được xác định là 𝑂(𝑔(𝑛)), kí hiệu 𝑓(𝑛) = 𝑂(𝑔(𝑛))
nếu tồn tại các hằng số C và số nguyên 𝑛0 sao cho |𝑓(𝑛)| ≤ 𝐶 |𝑔(𝑛)| với mọi 𝑛 ≥
𝑛0
Thông thường các hàm thể hiện độ phức tạp tính toán của thuật toán có dạng 𝑂(log2𝑛), 𝑂(𝑛), 𝑂(𝑛 log2𝑛), 𝑂(𝑛2), 𝑂(𝑛3), 𝑂(2𝑛), 𝑂(𝑛!), 𝑂(𝑛𝑛) Các hàm như
2𝑛, 𝑛𝑛,𝑛3, 𝑛2 được gọi là hàm mũ Các dạng như 𝑛 log2𝑛, log2𝑛 được gọi là các
hàm loại logarit Thuật toán với thời gian thực hiện có cấp hàm đa thức thì thường
hiệu quả và chấp nhận được
1.1.2.4 Các quy tắc xác định độ phức tạp thuật toán
• Quy tắc tổng: Giả sử 𝑇1(𝑛) và 𝑇2(𝑛) là thời gian thực hiện của 2 đoạn chương trình 𝑃1 và 𝑃2 kế tiếp nhau 𝑇1(𝑛) = 𝑂(𝑓(𝑛)); 𝑇2(𝑛) = 𝑂(𝑔(𝑛)) thì thời gian thực hiện 𝑃1 rồi 𝑃2 tiếp theo sẽ là: 𝑇1(𝑛) + 𝑇2(𝑛) = 𝑂(max(𝑓(𝑛), 𝑔(𝑛)))
• Quy tắc nhân: Giả sử 𝑇1(𝑛) và 𝑇2(𝑛) là thời gian thực hiện của 2 đoạn chương trình 𝑃1 và 𝑃2 tương ứng với 𝑇1(𝑛) = 𝑂(𝑓(𝑛)); 𝑇2(𝑛) = 𝑂(𝑔(𝑛)) thì thời gian thực hiện 𝑃1 rồi 𝑃2 lồng nhau sẽ là: 𝑇1(𝑛) 𝑇2(𝑛) = 𝑂(𝑓(𝑛) 𝑔(𝑛))
Chú ý: Trong các ngôn ngữ lập trình, chúng ta có thể đánh giá
+ Thời gian thực hiện mỗi câu lệnh gán, nhập dữ liệu, in kết quả là 𝑂(1)
+ Thời gian thực hiện mỗi chuỗi tuần tự các câu lệnh được tính theo quy tắc cộng + Thời gian thực hiện cấu trúc rẽ nhánh: Nếu E là biểu thức logic, S1, S2 là câu lệnh thì
If E then S 1 else S 2 là câu lệnh và có độ phức tạp là max(𝑓1(𝑛), 𝑓2(𝑛)) với 𝑓1(𝑛) là
độ phức tạp của S1, 𝑓2(𝑛) là độ phức tạp của S2
Trang 158
+ Thời gian thực hiện vòng lặp While do : Giả sử E là biểu thức logic, S là câu lệnh thì While E do S là câu lệnh Giả sử S có độ phức tạp là f(n) và g(n) là số lần tối đa thực hiện S Khi đó,thời gian thực hiện vòng lặp là O(f(n).g(n))
1.1.3 Vấn đề phân lớp các bài toán
Xét một bài toán tin học bất kì, chúng ta quan tâm đến các bài toán có lời giải
Vì độ phức tạp thuật toán đối với mỗi bài toán là khác nhau, do đó các bài toán cũng được phân chia thành các lớp thông qua độ phức tạp thuật toán giải chúng Chúng ta
có các khái niệm sau:
• Lớp bài toán P: là lớp các bài toán có thể giải được bằng thuật toán đơn định đa
+ Khái niệm dẫn về được: Bài toán B được gọi là dẫn về được bài toán A một cách
đa thức nếu có một thuật toán đơn định đa thức để giải bài toán A thì cũng có một thuật toán đơn định đa thức để giải bài toán B Ký hiệu 𝐵∞𝐴
+ Bài toán NP - khó (NP-hard): Bài toán A được gọi là NP - khó nếu có bài toán
𝐿∞𝐴 với ∀𝐿 ∈ 𝑁𝑃
+ Bài toán NP đầy đủ: Bài toán A được gọi là NP đầy đủ (NP-Complete) nếu: A là NP-khó và 𝐴 ∈ 𝑁𝑃
Từ đây chúng ta định nghĩa về lớp NPC như sau:
Định nghĩa: Lớp NPC là lớp các bài toán đầy đủ, có độ phức tạp hàm mũ Qua đó
Trang 169
Chẳng hạn sẽ là vô nghĩa khi đưa ra câu trả lời: cần sản xuất nửa cái bàn hay cần thuê 2,7 cái ô tô để vận chuyển hàng hóa Trong một số bài toán, chẳng hạn bài toán vận tải với các lượng hàng cung và cầu là các số nguyên, song nhiều bài toán khác không phải như vậy Vì thế trong mục này ta sẽ đề cập đến nội dung và phương pháp giải các bài toán tối ưu trên lưới các điểm nguyên hay trên các tập rời rạc, gọi tắt là bài toán quy hoạch rời rạc hay bài toán quy hoạch nguyên
Bài toán quy hoạch rời rạc có dạng sau:
Tìm cực đại của hàm 𝑓(𝑥, 𝑦) phụ thuộc hai nhóm biến x và y với các ràng buộc có dạng:
𝑔𝑖(𝑥, 𝑦) ≤ 0, 𝑖 = 1, 2, , 𝑚 , 𝑥 ∈ 𝐷 (1.1) trong đó: 𝑥 = (𝑥1, 𝑥2, , 𝑥𝑝), 𝑦 = (𝑦1, 𝑦2, , 𝑦𝑞), 𝑝 > 0, 𝑞 ≥ 0, D là tập hữu hạn các vectơ p - chiều, còn f, 𝑔𝑖 là những hàm cho trước của n biến số (𝑛 = 𝑝 + 𝑞) Nếu f, 𝑔𝑖 là các hàm tuyến tính và D là lưới các điểm nguyên, thì ta có bài toán quy hoạch nguyên tuyến tính, còn nếu D là tập các vectơ p thành phần 0 hay 1 thì ta
có bài toán quy hoạch nguyên 0 - 1
Nếu 𝑞 = 0, nghĩa là chỉ có các biến rời rạc 𝑥1, 𝑥2, , 𝑥𝑝 thì bài toán được gọi
là bài toán quy hoạch nguyên hoàn toàn Còn nếu 𝑞 > 0 thì bài toán được gọi là bài
toán nguyên bộ phận
1.2.2 Chú ý
Sở dĩ bài toán quy hoạch rời rạc còn được gọi là bài toán quy hoạch nguyên là
vì bất kỳ bài toán với các biến số chỉ nhận một số hữu hạn giá trị cho trước, đều có thể quy về bài toán trong đó các biến chỉ nhận các giá trị nguyên Ví dụ, giả sử biến
x biểu thị quy mô công suất của nhà máy điện cần xây dựng chỉ có thể lấy một trong các giá trị cho trước 𝑎1, 𝑎2, , 𝑎𝑘 (các quy mô công suất tiêu chuẩn) Khi đó bằng cách đặt:
𝑥 = 𝑎1𝑢1+ 𝑎2𝑢2+ +𝑎𝑘𝑢𝑘 (1.2)
với 𝑢1+ 𝑢2+ +𝑢𝑘 = 1, 𝑢𝑗 ∈ {0; 1}, 𝑗 = 1; 2; ; 𝑘
thì biến rời rạc x có thể được thay thế bởi một biến 𝑢𝑗 chỉ nhận giá trị 0 hay 1, gọi tắt là biến 0 - 1
Trang 171.3 Một số bài toán kinh điển
1.3.1 Bài toán vận tải
Có m kho hàng chứa một loại hàng hóa, lượng hàng hóa ở kho i là 𝑎𝑖 và n nơi tiêu thụ, nhu cầu ở nơi thu là 𝑏𝑗, 𝑐𝑖𝑗 là chi phí vận chuyển một đơn vị hàng từ điểm phát i đến điểm thu j Xác định các lượng hàng vận chuyển 𝑥𝑖𝑗 từ các điểm phát i tới các điểm thu j sao cho tổng chi phí là nhỏ nhất
Dạng toán học của bài toán là:
𝑖=1
= ∑ 𝑏𝑗𝑛
𝑗=1
(1.8)
Nếu các 𝑎𝑖 và 𝑏𝑗 là nguyên thì đa diện lồi xác định bởi các ràng buộc của bài toán có mọi đỉnh đều là nguyên Do đó ta có thể dùng phương pháp đơn hình để giải bài toán quy hoạch tuyến tính này, lời giải cuối cùng nhận được sẽ là một phương
án nguyên
Ví dụ Xét bài toán vận tải có 3 điểm phát và 4 điểm thu với ma trận chi phí
như sau:
Trang 181.3.2 Bài toán phân việc
Có n đơn vị sản xuất cần n loại sản phẩm, 𝑐𝑖𝑗 là chi phí cho đơn vị i sản xuất sản phẩm j Hãy phân công mỗi đơn vị sản xuất một sản phẩm sao cho tổng chi phí
𝑥[2;4] = 𝑥[3;2] = 𝑥[4;3] = 1
1.3.3 Bài toán cái túi
Có một cái túi chứa được nhiều nhất một trọng lượng là b, có n đồ vật cần mang, đồ vật j nặng 𝑎𝑗; giá trị của nó là 𝑐𝑗 Ký hiệu 𝑥𝑗 là số đồ vật j được đưa vào
Trang 191.3.4 Bài toán xếp hàng lên tàu
Một tàu chở hàng có trọng tải T và thể tích K, tàu chở n loại hàng, hàng loại j
có số lượng là 𝑠𝑗, có trọng lượng là 𝑎𝑗, thể tích 𝑏𝑗 và giá trị sử dụng là 𝑐𝑗 Xác định
số lượng hàng loại j cần xếp lên tàu 𝑥𝑗 để tổng giá trị hàng hóa trên tàu là lớn nhất Dạng toán học của bài toán là:
𝑗=1
≤ 𝑇
(1.21)
∑ 𝑏𝑗𝑥𝑗𝑛
𝑗=1
≤ 𝐾
(1.22)
𝑥𝑗 ∈ {0; 1; 2; ; 𝑠𝑗}, 𝑗 = 1; 2; ; 𝑛 (1.23)
Trang 2013
Ở đây, ta có thể giả sử các hệ số T, K, 𝑎𝑗, 𝑏𝑗, 𝑐𝑗 (với mọi j) đều là các số dương
1.3.5 Bài toán Knapsack
Mô hình bài toán Knapsack là vấn đề đã được nghiên cứu từ năm 1897 đến nay Viện nghiên cứu bài toán Knapsack đã được đưa ra đầu tiên trong các công trình của nhà toán học Tobias Dantzig (1884 - 1956) Các công trình tiếp theo được giới thiệu lần đầu tiên bởi Gallo, Hammer và Simeone vào năm 1960
Một công trình nghiên cứu các tác giả thuộc Đại học Stony Brook năm 1998 cho thấy rằng trong số 75 vấn đề về các bài toán NPC, bài toán Knapsack là 1 trong
18 bài toán quan trọng nhất trong lĩnh vực Toán và Công nghệ thông tin
Bài toán Knapsack - Bài toán xếp ba lô là một bài toán tối ưu tổ hợp Bài toán được đặt tên từ vấn đề chọn những gì quan trọng có thể nhét vừa vào trong một cái túi (với giới hạn khối lượng) để mang theo trong một chuyến đi Các bài toán tương
tự thường xuất hiện trong ngành kinh doanh, lý thuyết tổ hợp, lý thuyết độ phức tạp tính toán, lý thuyết mật mã học và một số lĩnh vực trong toán ứng dụng
Bài toán được phát biểu tổng quát như sau:
Có n đồ vật kí hiệu là 𝑥1, , 𝑥𝑛 Mỗi đồ vật 𝑥𝑗 có một giá trị 𝑝𝑗 và một thể tích
𝑤𝑗 với mọi j Thể tích mà có thể chứa trong ba lô là M Hãy xác định các phương án chọn các đồ vật sao cho số đồ vật chứa trong ba lô và tổng giá trị các đồ vật được chọn lớn nhất
Ví dụ Cho các hộp với giá trị các đồ vật và khối lượng tương ứng như sau:
{{4; 12}, {2; 2}, {2; 1}, {1; 1}, {10; 4}}, 𝑀 = 15 Chọn các hộp nào để làm cực đại lượng tiền trong khi giữ được tổng khối lượng dưới 15? Bài toán đa chiều có thể xét đến khối lượng riêng và kích thước của các hộp, đó là bài toán xếp vali điển hình Trong lớp các bài toán Knapsack, người ta thường đưa ra một số dạng bài toán điển hình như sau:
+ Bài toán xếp ba lô 0-1 là bài toán không hạn chế số đồ vật thuộc mỗi loại, bài
toán được mô hình hóa như sau:
Cực đại hóa hàm 𝑓(𝑋) = ∑𝑛𝑗=1𝑝𝑗𝑥𝑗 sao cho ∑𝑛𝑗=1𝑝𝑗𝑥𝑗 ≤ 𝑀 trong đó
Trang 2114
𝑋 = (𝑥1, 𝑥2, , 𝑥𝑛), 𝑥𝑗 = [0; 1], ∀𝑗 = {1; ; 𝑛}
+ Bài toán xếp ba lô bị chặn hạn chế số đồ vật thuộc mỗi loại không được vượt quá
một lượng xác định Bài xếp ba lô bị chặn có thể được phát biểu bằng mô hình toán học như sau:
Cực đại hóa hàm 𝑓(𝑋) = ∑𝑛𝑗=1𝑝𝑗𝑥𝑗 sao cho ∑𝑛𝑗=1𝑝𝑗𝑥𝑗 ≤ 𝑀 trong đó
𝑋 = (𝑥1, 𝑥2, , 𝑥𝑛), 𝑥𝑗 = [0; 1],
𝑥𝑗 ∈ [0; 𝑏𝑗],𝑏𝑗 ∈ ℕ, ∀𝑗 = {1; ; 𝑛}
Một trường hợp đặc biệt của bài toán Knapsack là bài toán thỏa mãn các tính chất sau đây:
• Là một bài toán quyết định
• Là một bài toán xếp ba lô dạng 0-1
• Phương án tối ưu là số đồ vật xếp vừa khít ba lô
Đối với dạng toán này, trong thực tế thường xuất hiện ở các dạng sau đây: Dạng 1: Cho tập các số nguyên, tồn tại hay không một tập con có đúng bằng 0?
Dạng 2: Cho tập các số nguyên dương, tồn tại hay không một tập con có tổng đúng bằng M?
Các bài toán này được gọi là tổng các tập con được sử dụng nhiều trong ngành mật mã học
Tổng quát hóa, từ mô hình bài toán Knapsack cũng có rất nhiều cách phát biểu khác nhau Sau đây là một số cách phát biểu bài toán:
Bài toán tập con cực đại: Cho một tập hữu hạn 𝑈 = {𝑢𝑖}, 𝑖 = 1; 2; ; 𝑛, mỗi phần tử 𝑢𝑖 ∈ 𝑈 có kích cỡ 𝑆(𝑢𝑖) và số tự nhiên B Hãy xác định một tập con 𝑈′ ⊆
𝑈 sao cho ∑ 𝑆(𝑢𝑖) = 𝐵 Trong đó 𝑢𝑖 ⊆ 𝑈′
Knapsack thuộc bài toán lớp NPC Nói chung không có thuật toán hữu hiệu nào để giải nó cho trường hợp bất kỳ Điều này không có nghĩa là tất cả các trường hợp đều có cùng độ phức tạp
Nhận xét:
Trang 2215
+ Bài toán trên có thể xác định lời giải chính xác bằng thuật toán duyệt toàn bộ theo tư tưởng như sau: Hãy duyệt mọi tổ hợp của các đồ vật, ứng với mỗi tổ hợp (𝑖1, 𝑖2, , 𝑖𝑘) thử điều kiện 𝑤(𝑖1) + 𝑤(𝑖2)+ +𝑤(𝑖𝑘) = 𝑀 để xác định nghiệm đúng Khi đó số phương án duyệt chính bằng 𝐶𝑛1+ 𝑐𝑛2+ +𝐶𝑛𝑛−1+ 𝐶𝑛𝑛; 2𝑛 tức là chúng ta có độ phức tạp của thuật toán là hàm mũ
+ Chúng ta có thể giải bài toán bằng thuật toán không đơn định đa thức như sau: sử dụng hàm CHOICE(0,1): là hàm chọn các đồ vật Khi đó bài toán được đưa
về bài toán sau đây:
Liệu có tồn tại tập chỉ số 𝑇 ⊂ {1; 2; ; 𝑛} thỏa mãn ∑𝑖∈𝑇𝑤
Khi đó bài toán được giải bằng thuật toán sau đây:
1 Cho i chạy tăng dần từ 1 đến n, thực hiện:
"Hãy xác định nhóm đồ vật đặt trong ba lô sao cho phần thừa còn lại là ít nhất" Khi
đó việc giải bài toán cũng được thực hiện tương tự, tuy nhiên chúng ta phải đưa thêm hàm mục tiêu 𝑓 = 𝑏 − (𝑎(𝑖1) + 𝑎(𝑖2)+ +𝑎(𝑖𝑘)) Khi đó phương án cần xác định là phương án thỏa mãn f đạt giá trị nhỏ nhất (𝑓 ≥ 0)
1.3.6 Bài toán Knapsack mở rộng
Dữ liệu vào: + Cho n đồ vật, đồ vật thứ i có thể tích là 𝑤𝑖, có giá trị là 𝑝𝑖
+ Cho 1 ba lô có thể tích M Kết quả ra: Xác định nhóm đồ vật thỏa mãn: tổng thể tích không vượt quá ba
lô đồng thời tổng giá trị là lớn nhất
Nhận xét:
+ Bài toán trên có thể xác định lời giải chính xác bằng thuật toán duyệt toàn bộ theo tư tưởng như sau: Kí hiệu (𝑥1; 𝑥2 ; 𝑥𝑛) là một phương án lựa chọn các đồ vật với 𝑥𝑖 ∈ {0; 1} Khi đó hãy duyệt mọi phương án (𝑥1; 𝑥2 ; 𝑥𝑛), ứng với mỗi
Trang 2316
phương án xác định điều kiện 𝑤1𝑥1+ 𝑤2𝑥2+ +𝑤𝑛𝑥𝑛 ≤ 𝑀 Nếu thỏa mãn thì xác định tiếp giá trị hàm mục tiêu 𝑓(𝑋) = 𝑝1𝑥1+ 𝑝2𝑥2+ +𝑝𝑛𝑥𝑛 từ đó xác định phương án tốt nhất Hiển nhiên bài toán đưa về bài toán duyệt mọi dãy nhị phân có
độ dài n với độ phức tạp hàm mũ
Thuật toán giải được mô tả như sau:
Danh sách biến • n, M, fmax: số nguyên
• X, W, P, Xluu: mảng số nguyên gồm n phần tử (n là hằng nguyên dương)
Thủ tục input • Tham số: Không
Trang 2417
Thủ tục output • Tham số: Không
• Mô tả: Xuất kết quả ra màn hình
4.2 Cho i chạy tăng từ 1 đến n, thực hiện: Gán Xluu[i] = X[i]
Kết thúc lệnh điều kiện (4) Kết thúc thủ tục
Kết thúc vòng lặp (1) Kết thúc thủ tục
Trang 25∑𝑛𝑖=1𝑤𝑖𝑥𝑖 ≤ 𝑀 và ∑𝑛𝑖=1𝑝𝑖𝑥𝑖 đạt giá trị lớn nhất Khi đó bài toán được giải bằng thuật toán sau đây:
1 Cho i chạy tăng dần từ 1 đến n, thực hiện:
1.1 Gán 𝑥𝑖 ← CHOICE(0,1)
1.2 Nếu ∑𝑛𝑖=1𝑥𝑖𝑤𝑖 ≤ 𝐵 thì xác định f, ngược lại thì sai
Kết thúc vòng lặp
Thuật toán trở thành thuật toán không đơn định đa thức với độ phức tạp O(n)
+ Bài toán Knapsack có thể giải bằng thuật toán GA với cấu trúc gen là dãy nhị phân và toán tử ghép đa điểm hoặc lại ghép mặt nạ được trình bày trong chương
2
Kết luận: Trong chương 1, luận văn trình bày những khái niệm cơ bản về bài toán -
thuật toán trong tin học, khái niệm về độ phức tạp của thuật toán và các nguyên tắc đánh giá độ phức tạp Trên cơ sở đó đưa ra nguyên tắc phân lớp các bài toán để tiến hành lựa chọn thuật toán tốt nhất giải các lớp bài toán trong thực tế Đưa ra mô hình bài toán Knapsack là một mô hình điển hình của lớp bài toán NP Các kiến thức này làm cơ sở để phân tích và thiết kế các thuật toán được trình bày trong các chương tiếp sau
Trang 2619
CHƯƠNG 2 MỘT SỐ THUẬT TOÁN XẤP XỈ
Nội dung chính của chương 2 sẽ nghiên cứu một số thuật toán xấp xỉ đã được nghiên cứu trong các kĩ thuật thiết kế thuật toán như: Thuật toán tham lam, thuật toán quy hoạch động, cùng các bài toán mẫu trong thực tế [3][4][5][7][9][10]
2.1 Khái niệm về thuật toán xấp xỉ
Nhiều bài toán có ý nghĩa rất quan trọng trong thực tiễn lại là NP đầy đủ Nếu
là một bài toán NP đầy đủ, ta không thể tìm một thuật toán thời gian đa thức để giải
nó chính xác Có hai cách tiếp cận để khắc phục tính đầy đủ NP
Thứ nhất, nếu các đầu vào thực tế là nhỏ, một thuật toán có thời gian thực hiện hàm mũ có thể hoàn toàn chấp nhận được
Thứ hai, vẫn có thể tìm các giải pháp gần tối ưu trong thời gian thực (hoặc
trong trường hợp xấu nhất hoặc tính trung bình) Trong thực tế để tính gần tối ưu
thường là đủ Một thuật toán trả về các giải pháp gần tối ưu được gọi là một thuật
toán xấp xỉ
Xét một bài toán tối ưu hóa, ở đó mỗi giải pháp có thể đưa ra có một mức hao phí dương, và ta muốn tìm giải pháp gần tối ưu Tùy thuộc vào bài toán, một giải pháp gần tối ưu có thể được định nghĩa là một giải pháp có mức hao phí khả dĩ cực đại hoặc một giải pháp có mức hao phí khả dĩ cực tiểu, bài toán có thể là bài toán cực đại hóa hoặc cực tiểu hóa
Một số thuật toán xấp xỉ cho bài toán có một cận tỉ số 𝑃(𝑛) nếu với bất kỳ đầu
vào có kích cỡ n, mức hao phí C của giải pháp mà thuật toán xấp xỉ tạo sẽ nằm trong một thừa số 𝑝(𝑛) của mức hao phí C* của một giải pháp tối ưu: max (𝐶
𝐶 ∗ cho ra thừa số qua đó mức hao phí của một giải pháp xấp xỉ lớn hơn mức hao phí của một giải pháp tối ưu Bởi tất
Trang 2720
cả giải pháp được mặc nhận có mức hao phí dương, các tỉ số này luôn được định nghĩa rõ ràng Cận tỉ số của một thuật toán xấp xỉ không bao giờ nhỏ hơn 1, bởi 𝐶
𝐶∗ < 1 Một thuật toán xấp xỉ có một cận lỗi tương đối ε(n) nếu |𝐶−𝐶∗|
𝐶∗ ≤ 𝜖(𝑛) Một lược đồ xấp xỉ cho một bài toán tối ưu hóa là một thuật toán xấp xỉ chấp nhận không những một bộ dữ liệu vào của bài toán, mà còn một giá trị 𝜖 > 0 làm đầu vào sao cho với bất kỳ ε, cố định, lược đồ là một thuật toán xấp xỉ có cận lỗi tương đối ε Ta nói rằng một lược đồ xấp xỉ có thời gian đa thức nếu với bất kỳ 𝜀 >
0 cố định, lược đồ chạy trong thời gian đa thức trong kích cỡ n của bộ dữ liệu đầu vào của nó
Thời gian thực hiện của một lược đồ xấp xỉ thời gian đa thức không tăng quá nhanh khi ε giảm Về lý tưởng nếu ε giảm theo một thừa số bất biến, thời gian thực hiện để đạt được mức xấp xỉ mong muốn không được gia tăng nhiều hơn một thừa
số bất biến Nói cách khác, ta muốn thời gian thực hiện là đa thức trong 1/ε cũng như trong n
Ta nói rằng một lược đồ xấp xỉ là một lược đồ xấp xỉ thời gian đa thức đầy đủ nếu thời gian thực hiện của nó là đa thức trong cả 1/ε lẫn trong kích cỡ n của bộ dữ liệu vào đầu vào, ở đó ε là cận lỗi tương đối cho lược đồ Ví dụ, lược đồ có thể có một thời gian thực hiện (1
𝜀)2 𝑛3 Với một lược đồ như vậy, mọi mức giảm thừa số bất biến trong ε đều có thể đạt được với một mức tăng thừa số bất biến tương ứng trong thời gian thực hiện
Sau đây chúng ta sẽ nghiên cứu một số phương pháp thiết kế các thuật toán xấp xỉ điển hình trong việc giải quyết các bài toán thuộc lớp NP
2.2 Các thuật toán tìm kiếm đường đi ngắn nhất trên mô hình đồ thị
2.2.1 Thuật toán Dijkstra
Cho đồ thị G có hướng liên thông cho bởi ma trận trọng số C Hãy xác định đường đi ngắn nhất từ s đến t
Thuật toán
Với mọi đỉnh 𝑥𝑘, ta đặt một nhãn tương ứng là [𝐿(𝑥𝑘), 𝑂(𝑥𝑘)] trong đó
Trang 2821
+ 𝐿(𝑥𝑘) là độ dài đường đi ngắn nhất từ s đến 𝑥𝑘
+ 𝑂(𝑥𝑘) là đỉnh đi trước 𝑥𝑘 trong đường đi ngắn nhất
Khi đó thuật toán Dijkstra được thực hiện theo các bước sau đây:
Bước 1: Với mọi đỉnh 𝑥𝑘 khác đỉnh s, gán nhãn [𝐶(𝑠, 𝑥𝑘), 𝑠], s là đỉnh cố định, các đỉnh 𝑥𝑘 là tạm thời
Bước 2 (Lặp): Với mọi 𝑥𝑘 tạm thời, xác định đỉnh có nhãn nhỏ nhất (Kí hiệu là 𝑥∗) Khi đó 𝑥∗ là cố định, các đỉnh khác là tạm thời
Bước 3: Với mọi 𝑥𝑘 tạm thời, thực hiện hiệu chỉnh lại nhãn theo quy tắc
Nếu 𝐿(𝑥𝑘) > 𝐿(𝑥∗) + 𝐶(𝑥∗, 𝑥𝑘) thì thực hiện
+ Tính lại 𝐿(𝑥𝑘) ← 𝐿(𝑥∗) + 𝐶(𝑥∗, 𝑥𝑘)
+ Xác định 𝑂(𝑥𝑘) = 𝑥∗
Bước 4: Quay lại bước 2
Thuật toán sẽ dừng khi đỉnh t trở thành cố định
Chú ý: Mấu chốt của thuật toán nằm ở bước 3 tức là nếu độ dài đường đi từ s đến
𝑥𝑘 (𝐿(𝑥𝑘)) mà lớn hơn độ dài đường đi từ s đến 𝑥∗ cộng với độ dài từ 𝑥∗ đến 𝑥𝑘: 𝐿(𝑥∗) + 𝐶(𝑥∗, 𝑥𝑘) thì hiển nhiên chúng ta sẽ chọn đường ngắn hơn là đường đi mà
đi qua 𝑥∗ và khi đó 𝑥∗ chính là đỉnh đi trước 𝑥𝑘 trong đường đi
Ví dụ: Cho đồ thị G (h.2.1):
Trang 29+ Để xác định đường đi ngắn nhất, ta xuất phát từ t đi ngược lại đỉnh đi trước t là
𝑥4, tiếp tục đi ngược lại đỉnh đi trước 𝑥4 là 𝑥3, tiếp tục đi ngược lại đỉnh đi trước 𝑥3
là 𝑥1, cuối cùng là s, ta thu được đường đi ngắn nhất là đường s -> 𝒙𝟏 -> 𝒙𝟑 -> 𝒙𝟒
-> t Độ dài đường đi ngắn nhất là 𝑑 = 5
+ Các đỉnh cố định trong bảng theo từng bước là các đỉnh có nhãn đánh dấu * + Việc xác định đường đi ngắn nhất thực chất là truy ngược lại vết O( ) trong nhãn
+ Trong thực hành, đề bài luôn cho G dưới dạng ma trận C, khi đó bắt buộc phải vẽ
đồ thị G tương ứng, từ đó mới dễ dàng thực hiện các bước của thuật toán
Thủ tục Dijkstra xuất phát từ đỉnh a bất kì được thực hiện như sau:
1 Cho mỗi đỉnh 𝑣 ∈ 𝑉, thực hiện:
1.1 Gán L[v] ← c[a, v]
1.2 Gán truoc[v] ← a
Kết thúc vòng lặp
Trang 3023
2 Trong khi 𝑧 ∉ 𝑆, thực hiện:
2.1 Đặt đỉnh u là đỉnh không thuộc S và có nhãn l(u) nhỏ nhất
2.2 Gán 𝑆 ← 𝑆 ∪ 𝑈
2.3 Cho mỗi đỉnh 𝑣 ∉ 𝑆, thực hiện:
Nếu 𝐿(𝑢) + 𝑐(𝑢, 𝑣) < 𝐿(𝑣) thì 2.3.1 Gán L(v) ← 𝐿(𝑢) + 𝑐(𝑢, 𝑣) 2.3.2 Gán truoc[v] ← u
Kết thúc lệnh điều kiện (2.3) Kết thúc vòng lặp (2)
2 (𝑛 − 1) phép toán do đó độ phức tạp của thuật toán cỡ 𝑂(𝑛2)
2.2.2 Thuật toán Floyd
Thuật toán Floyd được thiết kế theo kỹ thuật quy hoạch động và dựa trên nguyên lý tối ưu của Bellman
+ Dữ liệu vào: Đồ thị G(V, E) với n đỉnh, ma trận trọng số C với 𝐶[𝑢, 𝑣] ≥ 0;
𝑢, 𝑣 = 1 𝑛
+ Kết quả ra: Khoảng cách nhỏ nhất giữa mọi cặp đỉnh trong đồ thị
Tư tưởng: Hiệu chỉnh dần các giá trị A và P theo từng bước lặp theo thuật toán
Dijkstra
Kí hiệu:
+ Ma trận A để lưu độ dài đường đi ngắn nhất giữa mọi cặp đỉnh
Trang 3124
+ Mảng P, trong đó 𝑃[𝑖, 𝑗] = 𝑘 được hiểu là đường đi ngắn nhất từ đỉnh i đến đỉnh j đi qua đỉnh k
Khởi tạo: Đặt 𝐴0[𝑖, 𝑗] = 𝐶[𝑖, 𝑗], 𝑃0[𝑖, 𝑗] = 0, ∀𝑖, 𝑗 = 1 𝑛; tức là ban đầu A chứa
độ dài đường đi trực tiếp (không đi qua đỉnh nào cả)
Quá trình lặp: Kí hiệu 𝐴𝑖, 𝑃𝑖 là giá trị ma trận A, P tại bước lặp i
Tính giá trị cho ma trận A và ma trận P, với 𝐴𝑖[𝑖, 𝑗] và 𝑝𝑖[𝑖, 𝑗] được tính theo công thức sau:
Nếu 𝐴𝑖[𝑖, 𝑗] > 𝐴𝑖−1[𝑖, 𝑗 − 1] + 𝐴𝑖−1[𝑖 − 1, 𝑗] thì
𝐴𝑖[𝑖, 𝑗] = 𝐴𝑖−1[𝑖, 𝑗 − 1] + 𝐴𝑖−1[𝑖 − 1, 𝑗]; 𝑝𝑖[𝑖, 𝑗] = 𝑖;
Quá trình trên được thực hiện cho đến đủ n bước Khi đó mảng 𝐴𝑛 lưu giá trị đường
đi ngắn nhất giữa mọi cặp đỉnh và mảng 𝑃𝑛 lưu giá trị vết đường đi ngắn nhất giữa mọi cặp đỉnh
Thủ tục Floyd được thực hiện như sau:
1 Cho i chạy tăng từ 1 đến n, thực hiện:
Cho j chạy tăng từ 1 đến n, thực hiện:
1.1 Gán A[i, j] ← C[i, j] (sao chép ma trận C sang A) 1.2 Gán P[i, j] ← 0
Kết thúc vòng lặp (1)
2 Cho k chạy tăng từ 1 đến n, thực hiện:
Cho i chạy tăng từ 1 đến n, thực hiện:
Cho j chạy tăng từ 1 đến n, thực hiện:
Nếu 𝐴[𝑖, 𝑗] > 𝐴[𝑖, 𝑘] + 𝐴[𝑘, 𝑗] thì 2.1 Gán 𝐴[𝑖, 𝑗] ← 𝐴[𝑖, 𝑘] + 𝐴[𝑘, 𝑗]
2.2 Gán 𝑃[𝑖, 𝑗] ← k Kết thúc lệnh điều kiện (2), kết thúc vòng lặp Kết thúc thủ tục
Nhận xét
Thuật toán Floyd bản chất là một thuật toán quy hoạch động Vì độ phức tạp thời gian của thuật toán là 𝑂(𝑛3) (3 vòng lặp lồng nhau) nên ta có thể sử dụng cho
Trang 3225
đồ thị có số đỉnh 𝑛 ≤ 400 Với các bài toán yêu cầu tìm đường đi ngắn nhất của toàn bộ cặp cạnh trong đồ thị, Floyd là một lựa chọn hợp lý so với các thuật toán tìm đường đi ngắn nhất trên nguồn đơn như Dijkstra Dễ thấy:
• Thuật toán Dijkstra có độ phức tạp 𝑂(𝑛 + |𝐸|) log 𝑛 Khi thực hiện n lần gọi, ta
có độ phức tạp trở thành 𝑂(𝑛3 log 𝑛) nếu |𝐸| = 𝑂(𝑛2)
2.3 Một số thuật toán xấp xỉ sử dụng kỹ thuật Quy hoạch động và tham lam
2.3.1 Phương pháp quy hoạch động
Phương pháp quy hoạch động cùng nguyên lí tối ưu được nhà toán học Mỹ
Richard Bellman (1920 - 1984) đã đề xuất vào những năm 50 của thế kỷ XX
Phương pháp này đã được áp dụng để giải nhiều bài toán thực tế đặc biệt là những bài toán tối ưu, ví dụ như: việc xác định các phương án tối ưu trong mô hình kỹ thuật công nghệ, tổ chức sản xuất, kế hoạch hóa kinh tế
Quy hoạch động là kỹ thuật thiết kế bottom-up (từ dưới lên) Nó được bắt đầu với những trường hợp con nhỏ nhất (thường là đơn giản nhất và giải được ngay) Bằng cách tổ hợp các kết quả đã có (không phải tính lại) của các trường hợp con, sẽ đạt tới kết quả của trường hợp có kích thước lớn dần lên và tổng quát hơn, cho đến khi cuối cùng đạt tới lời giải của trường hợp tổng quát nhất Để thấy rõ về phương pháp này ta đi tìm hiểu chi tiết ở các nội dung tiếp theo
2.3.1.1 Một số khái niệm
Quy hoạch động (Dynamic Programming) là phương pháp giải một bài toán bằng cách tổ hợp lời giải các bài toán con của nó Phương pháp này dùng để giải bài toán tối ưu có bản chất đệ quy, tức là việc tìm phương án tối ưu cho bài toán đó có thể đưa về tìm phương án tối ưu của một số hữu hạn các bài toán con Nếu tìm đúng
hệ thức thể hiện bản chất quy hoạch động của bài toán và khéo tổ chức dữ liệu thì ta
có thể xử lý được những tập dữ liệu khá lớn
Khi đó, ta có một số khái niệm liên quan như sau:
+ Bài toán giải theo phương pháp quy hoạch động gọi là bài toán quy hoạch động
Trang 3326
+ Công thức phối hợp nghiệm của các bài toán con để có nghiệm của bài toán
lớn gọi là công thức truy hồi của quy hoạch động
+ Tập các bài toán nhỏ nhất có ngay lời giải để từ đó giải quyết các bài toán
lớn hơn gọi là cơ sở quy hoạch động
+ Không gian lưu trữ lời giải các bài toán con để tìm cách phối hợp chúng gọi
là bảng phương án của quy hoạch động
Tư tưởng Phương pháp quy hoạch động dựa trên một nguyên lý quan trọng, đó
là Nguyên lý tối ưu của Bellman Nguyên lý được phát biểu như sau: "Quy hoạch
động là lớp các bài toán mà quyết định ở bước thứ i phụ thuộc vào quyết định ở các bước đã xử lý trước hoặc sau đó" Quy hoạch động bắt đầu từ việc giải các bài toán
nhỏ nhất (bài toán cơ sở) để từ đó từng bước giải quyết những bài toán lớn hơn cho tới khi giải được bài toán lớn nhất (bài toán ban đầu) Tư tưởng cơ bản của quy
hoạch động là: tránh tính toán lại mọi thứ hai lần mà lưu giữ kết quả đã tìm kiếm
được vào một bảng làm giả thiết cho việc tìm kiếm những kết quả của trường hợp sau Chúng ta sẽ làm đầy dần giá trị của bảng này bởi các kết quả của những trường
hợp trước đã được giải Kết quả cuối cùng chính là kết quả của bài toán cần giải Nói cách khác phương pháp quy hoạch động đã thể hiện sức mạnh của nguyên lý chia để trị đến cao độ
Tư tưởng của thuật toán quy hoạch động khá đơn giản Tuy nhiên khi áp dụng thuật toán vào trường hợp cụ thể lại không dễ dàng (điều này cũng tương tự nguyên tắc Dirichlet trong toán học)
2.3.1.2 Các bước thực hiện
Bước 1: Lập hệ thức
Dựa vào nguyên lý tối ưu tìm cách chia quá trình giải bài toán thành từng giai đoạn, sau đó tìm hệ thức biểu diễn tương quan quyết định của bước đang xử lý với các bước đã xử lý trước đó Hoặc tìm cách phân rã bài toán thành các "bài toán con" tương tự có kích thước nhỏ hơn, tìm hệ thức quan hệ giữa kết quả bài toán kích thước đã cho với các kết quả của các bài toán con cùng kiểu có kích thước nhỏ hơn của nó dạng hàm hoặc thủ tục đệ quy
Trang 3427
Khi đã có hệ thức tương quan chúng ta có thể xây dựng ngay thuật giải, tuy nhiên hệ thức này thường là các biểu thức đệ quy, do đó dễ gây ra hiện tượng tràn miền nhớ khi ta tổ chức chương trình trực tiếp bằng đệ quy
Bước 2: Tổ chức dữ liệu và chương trình
Tổ chức dữ liệu sao cho đạt các yêu cầu sau:
a) Dữ liệu được tính toán dần theo các bước
b) Dữ liệu được lưu trữ để giảm lượng tính toán lặp lại
c) Kích thước miền nhớ dành cho lưu trữ dữ liệu càng nhỏ càng tốt, kiểu dữ liệu được chọn phù hợp, nên chọn đơn giản dễ truy cập
Bước 3: Làm tốt
Làm tốt thuật toán bằng cách thu gọn hệ thức và giảm kích thước miền nhớ Thường tìm cách dùng mảng một chiều thay cho mảng hai chiều nếu giá trị một dòng (hoặc cột) của mảng hai chiều chỉ phụ thuộc một dòng (hoặc cột) kề trước Trong một số trường hợp có thể thay mảng hai chiều với các giá trị phần tử chỉ nhận giá trị 0, 1 bởi mảng hai chiều mới bằng cách dùng kỹ thuật quản lý bit
Quy hoạch động là một phương pháp phân tích và thiết kế thuật toán cho phép giảm bớt thời gian thực hiện khi khai thác tốt các đặc điểm của bài toán Tuy nhiên thông thường quy hoạch động lại đòi hỏi nhiều không gian bộ nhớ hơn (để thực hiện ghi nhớ) Ngày nay, với sự mở rộng bộ nhớ máy tính và nhiều phần mềm lập trình mới cho phép sử dụng bộ nhớ rộng rãi hơn thì phương pháp quy hoạch động càng có nhiều khả năng giải các bài toán trước đây khó giải quyết do hạn chế bộ nhớ máy tính
Ví dụ Xây dựng quy hoạch động giải bài toán Knapsack
Xét bài toán Knapsack
Dữ liệu vào: + Cho n đồ vật, đồ vật thứ i có thể tích là 𝑤𝑖, có giá trị là 𝑝𝑖
+ Cho 1 ba lô có thể tích M Kết quả ra: Nhóm đồ vật thỏa mãn: tổng thể tích không vượt quá ba lô đồng thời tổng giá trị là lớn nhất
Phân tích:
Trang 3528
Nếu gọi 𝐹[𝑖, 𝑗] là giá trị lớn nhất có thể có bằng cách chọn trong các đồ vật {1; 2; ; 𝑖} với thể tích j Thì giá trị lớn nhất khi được chọn trong số n đồ vật với giới hạn thể tích M chính là 𝐹[𝑛, 𝑚]
• Công thức truy hồi tính 𝐹[𝑖, 𝑗]
Với giới hạn thể tích j, việc chọn tối ưu trong số các đồ vật {1; 2; ; 𝑖 − 1; 𝑖}
để có giá trị lớn nhất sẽ có hai khả năng:
• Nếu không chọn đồ vật thứ i thì 𝐹[𝑖, 𝑗] là giá trị lớn nhất có thể bằng cách chọn trong số các đồ vật {1; 2; ; 𝑖 − 1} với thể tích là j Tức là 𝐹[𝑖, 𝑗] =𝐹[𝑖 − 1, 𝑗]
• Nếu có chọn đồ vật thứ i (chỉ xét khi 𝑊𝑖 ≤ 𝑗) thì 𝐹[𝑖, 𝑗] bằng giá trị đồ vật thứ i và 𝑉𝑖 cộng với giá trị lớn nhất có thể có được bằng cách chọn trong số các đồ vật {1; 2; 𝑖 − 1} với thể tích 𝑗 − 𝑊𝑖 Tức là về mặt giá trị thu được: 𝐹[𝑖, 𝑗] = 𝑉𝑖 +𝐹[𝑖 − 1, 𝑗 − 𝑊𝑖]
Vì theo cách xây dựng 𝐹[𝑖, 𝑗] là giá trị lớn nhất có thể, nên 𝐹[𝑖, 𝑗] sẽ là giá trị lớn nhất trong 2 giá trị thu được ở trên
Cơ sở quy hoạch động:
Dễ thấy 𝐹[0, 𝑗] bằng giá trị lớn nhất có thể bằng cách chọn trong số 0 đồ vật bằng 0
Tính bảng phương án:
Bảng phương án F gồm 𝑛 + 1 dòng, 𝑀 + 1 cột, trước tiên được điền cơ sở quy hoạch động: Dòng 0 gồm toàn số 0 Sử dụng công thức truy hồi, dùng dòng 0 tính dòng 1, dùng dòng 1 tính dòng 2 đến khi tính hết dòng n
Trang 3629
Tính xong bảng phương án thì ta quan tâm đến 𝐹[𝑛, 𝑀] đó chính là giá trị lớn nhất thu được khi chọn trong cả n đồ vật với thể tích M Nếu 𝐹[𝑛, 𝑀] =𝐹[𝑛 − 1, 𝑀] thì tức là không chọn đồ vật thứ n, ta truy tiếp 𝐹[𝑛 − 1, 𝑀] Còn nếu 𝐹[𝑛, 𝑀] ≠ 𝐹[𝑛 − 1, 𝑀] thì ta thông báo rằng phép chọn tối ưu có chọn đồ vật thứ n
và truy tiếp 𝐹[𝑛 − 1, 𝑀 − 𝑊𝑛] Cứ tiếp tục cho tới khi truy lên tới hàng 0 của bảng phương án
Đánh giá
Bài toán Knapsack có thể dễ dàng giải được nếu M không lớn, nhưng khi M lớn thì thời gian chạy trở nên không thể chấp nhận được Phương pháp này không thể làm việc được khi M và trọng lượng/kích thước là những số thực thay vì số nguyên Thuật toán quy hoạch động để giải bài toán Knapsack có thời gian chạy với
tỉ lệ n*M
2.3.2 Phương pháp tham lam
2.3.2.1 Giới thiệu chung
Thuật toán tham lam (Greedy algorithms) là một thuật toán giải quyết một số bài toán theo kiểu heuristic để tìm kiếm lựa chọn tối ưu địa phương ở mỗi bước đi với hy vọng tìm được tối ưu toàn cục Ưu điểm của thuật toán tham lam là dễ đề
xuất theo tư tưởng tự nhiên (Miếng ngon ăn trước) Trong hầu hết các bài toán tối
ưu, để nhận được nghiệm tối ưu chúng ta có thể đưa về thực sự thực hiện một dãy các lựa chọn Ý tưởng của chiến lược tham lam là tại mỗi bước ta sẽ lựa chọn một phương án được xem là tốt nhất trong ngữ cảnh nào đó được xác định bởi bài toán tức là việc lựa chọn ở mỗi bước chính là phương án tối ưu địa phương Tùy theo từng bài toán mà ta đưa ra tiêu chuẩn lựa chọn thích hợp
Các thuật toán tham lam (greedy algorithm) nói chung là đơn giản và hiệu quả (vì các tính toán để tìm ra quyết định tối ưu địa phương thường là đơn giản) Tuy nhiên các thuật toán tham lam có thể không tìm được nghiệm tối ưu, nói chung nó chỉ cho ra nghiệm gần tối ưu, nghiệm tương lai tốt Nhưng cũng có nhiều thuật toán được thiết kế theo kỹ thuật tham lam cho ta nghiệm tối ưu, chẳng hạn thuật toán Dijkstra tìm đường đi ngắn nhất từ một đỉnh tới các đỉnh còn lại trong đồ thị vô
Trang 3730
hướng Phương pháp tham lam là kỹ thuật thiết kế thường được dùng để giải các bài toán tối ưu, phương pháp được tiến hành theo nhiều bước, tại mỗi bước theo một lựa chọn nào đó (xác định bằng một hàm chọn) sẽ tìm một lời giải tối ưu cho bài toán nhỏ tương ứng Lời giải của bài toán được bổ sung dần từng bước từ lời giải của các bài toán con Các lời giải tìm được bằng phương pháp tham lam thường chỉ
là chấp nhận theo điều kiện nào đó, chưa chắc là tối ưu
2.3.2.2 Đặc trưng của phương pháp tham lam
Phương pháp tham lam cần tìm một trật tự hợp lí để duyệt dữ liệu nhằm đạt được mục tiêu một cách chắc chắn và nhanh chóng Thông thường dữ liệu được duyệt theo một trong hai trật tự là tăng hoặc giảm dần theo một chi tiêu nào đó Thuật toán tham lam có trường hợp luôn tìm ra đúng phương án tối ưu, có trường hợp không Nhưng trong trường hợp thuật toán tham lam không tìm ra đúng phương
án tối ưu, chúng ta thường thu được một phương án khả dĩ chấp nhận được Với một bài toán có nhiều thuật toán để giải quyết, thông thường thuật toán tham lam có tốc độ tốt hơn hẳn so với các thuật toán tối ưu tổng thể
2.3.2.3 Các thành phần cơ bản
Thuật toán tham lam có 5 thành phần:
• Một tập hợp các ứng viên để từ đó tạo ra lời giải
• Một hàm lựa chọn để lựa chọn ứng viên tốt nhất để bổ sung vào lời giải
• Một hàm khả thi dùng để quyết định một ứng viên có thể là một lời giải
• Một hàm mục tiêu để ấn định giá trị của lời giải hoặc một lời giải chưa hoàn chỉnh
• Một hàm đánh giá để chỉ ra khi nào ta tìm ra một lời giải hoàn chỉnh
Không có cách tổng quát cho một thuật toán tham lam giải quyết một bài toán tối ưu, nhưng chiến lược lựa chọn tham lam và cấu trúc con tối ưu là hai thành phần then chốt, thực tế đã chứng minh rằng các bài toán có 2 thuộc tính này là rất thuận lợi cho việc xây dựng một thuật toán tham lam giải quyết nó
Hai yếu tố quyết định tới tính tham lam của thuật toán:
Trang 3831
+ Tính lựa chọn tham lam: Đây là thành phần then chốt đầu tiên, một giải
pháp tối ưu toàn cục có thể đạt được bằng cách lựa chọn tối ưu cục bộ (tham lam) Như vậy, khi có nhiều sự lựa chọn thì ta lựa chọn phương án nào tốt nhất ở hiện tại trong bài toán đang xét mà không cần quan tâm đến kết quả của các bài toán con của nó
+ Cấu trúc con tối ưu: Một bài toán có cấu trúc con tối ưu nếu giải pháp tối
ưu cho bài toán này chứa trong nó các giải pháp tối ưu cho các bài toán con Thuộc tính này là điểm quyết định để có thể giải bài toán bằng phương pháp tham lam được hay không?
Thuật toán tham lam có được một giải pháp tối ưu cho một bài toán bằng cách thực hiện một chuỗi các lựa chọn Đối với mỗi quyết định chỉ ra trong thuật toán sự lựa chọn này thường là tốt nhất tại thời điểm được chọn Nếu có thể chứng minh rằng một thuật toán tham lam cho ra kết quả tối ưu toàn cục cho một lớp bài toán nào đó, thì thuật toán thường sẽ trở thành phương pháp được chọn lựa, vì nó chạy nhanh hơn các phương pháp tối ưu hóa khác Tuy nhiên đại đa số các trường hợp, thuật toán tham lam chỉ cho nghiệm gần đúng với nghiệm tối ưu
2.3.2.4 Các bước xây dựng thuật toán tham lam
Thuật toán tham lam được xây dựng theo từng bước như sau:
• Xác định cấu trúc bên trong tối ưu của bài toán
• Xây dựng một giải pháp đệ quy
• Chứng minh rằng tại mỗi bước của thuật toán đệ quy, lựa chọn tham lam là một trong những lựa chọn sẽ dẫn đến kết quả tối ưu
• Chỉ ra rằng sau mỗi lần chọn tham lam thì một trong những bài toán con sẽ rỗng
• Xây dựng thuật toán đệ quy cho chiến lược tham lam
• Biến đổi thuật toán đệ quy thành thuật toán lặp
Qua các bước này đã mô tả nguồn gốc cơ bản của tư tưởng quy hoạch động của thuật toán tham lam Tuy nhiên ta thường tổ chức hiệu quả các bước trên khi
Trang 392.3.2.5 Mô hình thuật toán tham lam
Ta xây dựng tập S dần từng bước, bắt đầu từ tập rỗng Tại mỗi bước ta sẽ chọn một phần tử "tốt nhất" trong các phần tử còn lại của A để đưa vào S Việc lựa chọn một phần tử như thế ở mỗi bước được hướng dẫn bởi hàm chọn Phần tử được chọn
sẽ bị loại khỏi tập A Nếu khi thêm phần tử được chọn vào tập S mà S vẫn còn thỏa mãn các điều kiện của bài toán thì ta mở rộng S bằng cách thêm vào phần tử được chọn
Thuật toán tham lam tổng quát được mô tả như sau:
+ Nếu 𝑆 ∪ {𝑥} thỏa mãn yêu cầu bài toán thì thêm {𝑥} vào tập S
Thuật toán tham lam được mô tả bằng thủ tục sau:
• Tên thủ tục: Greedy
• Các tham số: A, S // A là một tập các ứng cử viên, X là tập quyết định - nghiệm
• Thực hiện:
Trang 40Ví dụ: Xét lại bài toán Knapsack
Dữ liệu vào: + Cho n đồ vật, đồ vật thứ i có thể tích là 𝑤𝑖, có giá trị là 𝑝𝑖
+ Cho 1 ba lô có thể tích M Kết quả ra: Xác định nhóm đồ vật thỏa mãn: tổng thể tích không vượt quá ba lô đồng thời tổng giá trị là lớn nhất
Phân tích:
Hiển nhiên theo tư tưởng tự nhiên thì để lấy đồ vật có lợi nhất, chúng ta cần thực hiện chiến lược lấy đồ vật có giá trị cao nhất với thể tích nhỏ nhất tại thời điểm hiện tại cho đến khi không thể lấy được nữa thì dừng Vì vậy ta xây dựng thuật toán theo tư tưởng tham lam như sau:
Bước 1: Sắp xếp các đồ vật theo thứ tự giảm dần của tỉ số 𝑝𝑖
𝑤𝑖 (𝑖 = 1; 2; ; 𝑛)
Bước 2: Khởi động tập hợp 𝑆 = ∅ là tập các đồ vật cần lấy
Bước 3: Kết nạp lần lượt các đồ vật theo thứ tự sắp xếp vào S, mỗi lần kết nạp cần
kiểm tra thể tích của S phải không vượt quá M
Quá trình sẽ kết thúc khi không thể kết nạp thêm đồ vật nào vào S