Bài toán cây khung nhỏ nhất Bài toán cây khung cây bao trùm nhỏ nhất của đồ thị là một trong số những bài toán tối ưu trên đồ thị tìm được ứng dụng trong nhiều lĩnh vực khác nhau của đời
Trang 1BỘ GIÁO DỤC VÀ ĐÀO TẠO TRƯỜNG ĐẠI HỌC SƯ PHẠM TP HỒ CHÍ MINH
KHOA CNTT
Tiểu Luận Đề Tài Nhóm:
ĐỀ TÀI 3 MINH HOA TRỰC QUAN BẰNG GIAO DIỆN ĐỒ HỌA
HAI THUẬT TOÁN LÝ THUYẾT ĐỒ THỊ
FORD-BELLMAN VÀ PRIM
Học phần: 2111COMP170101 – Lý thuyết đồ thị và ứng dụng
Học kỳ I Năm học 2021-2022
Giảng viên hướng dẫn: Lương Trần Ngọc Khiết
Họ và tên: Phạm Đức Tài
MSSV :44.01.104.186.
Các thành viên trong nhóm:
Trần Thanh Bình 46.01.104.014
Đinh Trần Thanh Tú 46.01.104.205
Trương Thế Nhật 46.01.104.129
Phạm Đức Tài 44.01.104.186
Trang 2MỤC LỤC:
N I DUNG Ộ 2
CHƯƠNG 1 GIỚI THIỆU THUẬT TOÁN PRIM 2
1.1 S ra đ i c a thu t toán Prim ự ờ ủ ậ 2
1.2.Mô t thu t toán ả ậ 2
CHƯƠNG 2: GIỚI THIỆU THUẬT TOÁN FORD-BELLMAN 4
2.1.S ra đ i c a thu t toán ford-bellman ự ờ ủ ậ 4
2.2 Mô t thu t toán ả ậ 4
2.5.Đánh giá thu t toán ậ 5
CHƯƠNG 3 NỘI DUNG THỰC HÀNH 6
3.1.Gi i thích cách ho t đ ng c a ng d ng gi i thu t Prim bằằng Windows Form: ả ạ ộ ủ ứ ụ ả ậ 6
3.2.Thu t toán Forbell: ậ 7
B NG PHÂN CÔNG CÔNG VI C Ả Ệ 8
TÀI LI U THAM KH O Ệ Ả 9
Trang 3NỘI DUNG CHƯƠNG 1 GIỚI THIỆU THUẬT TOÁN PRIM
Bài toán tối ưu là một bài toán muôn thưở của ngành tin học bởi nó có ứng dụng hết sức rộng rãi và đa dạng Các bài toán tối ưu thường xuất hiện trong các ngành kinh
tế và kĩ thuật cũng vì lý do này mà trên thế giới có rất nhiều thuật toán để giải các bài toán tối ưu Một trong số đó có thể kể đến là thuật toán Prim
1.1 Bài toán cây khung nhỏ nhất
Bài toán cây khung (cây bao trùm) nhỏ nhất của đồ thị là một trong số những bài toán tối ưu trên đồ thị tìm được ứng dụng trong nhiều lĩnh vực khác nhau của đời sống Để minh họa cho những ứng dụng đó, chúng ta cùng tham khảo ba mô hình thực tế tiêu biểu của bài toán:
• Bài toán xây dựng hệ thống cable: Giả sử muốn xây dựng một hệ thống cable điện thoại nối n điểm của một mạng viễn thông sao cho điểm bất kì nào trên mạng đều
có đường truyền tin tới các điểm khác Biết chi phí xây dựng hệ thống cable từ điểm
i đến điểm j là c[i,j] Hãy tìm cách xây dựng hệ thống mạng cable sao cho chi phí là nhỏ nhất
• Bài toán xây dựng hệ thống đường sắt: Giả sử ta muốn xây dựng một hệthống đường sắt nối n thành phố sao cho hành khách có thể đi từ bất kỳ mộtthành phố nào đến bất kỳ một trong các thành phố còn lại Mặt khác trênquan điểm kinh tế đòi hỏi
là chi phí xây dựng hệ thống đường phải nhỏ nhất.Rõ ràng đồ thị mà đỉnh là các thành phố còn các cạnh là các tuyến đường sắtnối các thành phố tương ứng với phương án xây dựng tối ưu phải là cây Vìvây, bài toán đặt ra dẫn về bài toán tìm cây khung nhỏ nhất trên đồ thị đầy đủn đỉnh, mỗi đỉnh tương ứng với một thành phố, với độ dài trên các các cạnhchính là chi phí xây dựngđường ray nối hai thành phố tương ứng (chú ý là trong bài toán này ta giả thiết là không xây dựng tuyến đường sắt có các nhà ga phântuyến nằm ngoài các thành phố)
• Bài toán nối mạng máy tính: Cần nối mạng một hệ thống gồm n máy tính đánh số
từ 1 đến n Biết chi phí nối máy i với máy j là c[i,j], i,j = 1, 2, ,n ( thông thường chi phí này phụ thuộc vào độ dài cáp nối cần sử dụng) Hãy tìm cáchnối mạng sao cho tổng chi phí nối mạng là nhỏ nhất.Và bài toán cây khung nhỏ nhất được phát biểu như sau:Cho đồ thị G= là đồ thị vô hướng liên thông với tập đỉnh
V={1,2,3…,n}và tập cạnh E gồm m cạnh Mỗi cạnh e của đồ thị được gán với một sốc(e) được gọi là trọng số của cạnh Giả sử H= là một cây khung của đồ thị G Ta gọi độ dài c(H) của cây khung H là tổng độ dài các cạnh :
c(H)= ∑ c(e) e T∈
Trang 4Bài toán đặt ra là, trong số các cây khung của đồ thị hãy tìm cây khung có độ dài nhỏ nhất của đồ thị
Để giải bài toán tìm cây khung nhỏ nhất, chúng ta có thể liệt kê toàn bộ cây khung
và chọn trong số những cây khung đã liệt kê một cây khung có độ dài nhỏ nhất Tuy nhiên số cây khung của mỗi đồ thị lại rất lớn cỡ nn-2 do vậy phương án này hoàn toàn không khả thi và chỉ cần với đồ thị với số đỉnh cỡ chục thì phương án này trở nên vô dụng
Rất may là chúng ta đã có hai thuật toán vô cùng hiệu quả để giải quyết bài toàn trên đó chính là thuật toán Prim và thuật toán Kruskal
Chúng ta sẽ cùng tìm hiểu về thuật toán Prim
1.2 Sự ra đời của thuật toán Prim
Thuật toán Prim còn được mang tên là người láng giềng gần nhất, hay phươngpháp lân cận gần nhất,là một thuật toán tham lam để tìm cây khung nhỏ nhất của một đồ thị vô hướng có trọng số liên thông Nghĩa là nó tìm một tập hợp các cạnh của đồ thị tạo thành một cây chứa tất cả các đỉnh, sao cho tổng trọng số các cạnh của cây là nhỏ nhất
Thuật toán được tìm ra năm 1930 bởi nhà toán học người Séc Vojtěch Jarník và sau
đó bởi nhà nghiên cứu khoa học máy tính Robert C Prim năm 1957 và một lần nữa độc lập bởi Edsger Dijkstra năm 1959 Do đó nó còn có tên gọi là thuật toán DJP, thuật toán Jarník, hay thuật toán Prim–Jarník.II
1.3.Mô tả thuật toán
Begin
Bước 1 (Khởi tạo):
VH = {s}; //Tập đỉnh cây khung thiết lập ban đầu là s
V=V\{s}; //Tập đỉnh V được bớt đi
sT=∅; //Tập cạnh cây khung thiết lập ban đầu là ∅
D(H)=0;//Độ dài cây khung được thiết lập là 0
Bước 2 (Lặp):
while(V≠ ) do{
e=<u,v>; //cạnh có độ dài nhỏ nhất thỏa mãn u V, v VH∈ ∈
d(H)=d(H)+d(e);//thiết lập độ dài cây khung nhỏ nhất
T=T∪ {e};//Kết nạp e vào cây khung
V=V\{u};//Tập đỉnh V bớt đi đỉnh u
VH=VH∪{u};//Tập đỉnh VH thêm vào đỉnh u
}
Trang 5Bước 3 (Trả lại kết quả):
if(|T|<n-1) then < Đồ thị không liên thông>;
else Return(T,d(H));
End
1.4 Đánh giá thuật toán
1.4.1 Độ phức tạp thuật toán
Xét về độ phức tạp thuật toán sử dụng ma trận kề, thuật toán Prim có độ phức tạp là O(n2 ) Nếu kết hợp thuật toán Prim với cấu trúc Heap sẽ được một thuật toán có độ phức tạp O((m+n)lgn)
Do thời gian nghiên cứu hạn hẹp nên chúng tôi xin phép chỉ trình bày cách lập trình
sử dụng ma trận kề
1.4.2 Ưu điểm so với Kruskal
Thuật toán Kruskal làm việc kém hiệu quả với những đồ thị dày (số cạnh cỡ m≈n(n-1)/2) Trong trường hợp đó thuật toán Prim tỏ ra hiệu quả hơn Tuy nhiên khi làm việc với đồ thị thưa người ta thường lựa chọn thuật toán Kruskal thay vì thuật toán Prim
Trang 6CHƯƠNG 2: GIỚI THIỆU THUẬT TOÁN FORD-BELLMAN
Thuật toán Bellman-Ford là một thuật toán tính các đường đi ngắn nhất nguồn đơn trong một đồ thịcó hướng có trọng số (trong đó một số cung có thể có trọng số âm) Thuật toán Dijkstra giải cùng bài toánnày với thời gian chạy thấp hơn, nhưng lại đòi hỏi trọng số của các cung phải có giá trị không âm
Do đó,thuật toán Bellman-Ford thường chỉ được dùng khi có các cung với trọng số âm.Thuật toán Bellman Ford chạy trong thời gian O(V·E), trong đó V là số đỉnh và
E là số cung của đồ thị
2.1.Chứng minh tính đúng đắn
Tính đúng đắn của thuật toán có thể được chứng minh bằng quy nạp Thuật toán có thể được phát biểu chính xác theo kiểu quy nạp như sau:
Bổ đề Sau i lần lặp vòng for:
2.1.1 Nếu Khoảng_cách(u) không có giá trị vô cùng lớn, thì nó bằng độ dài của một đường đi nào đó từ stới u;
2.1.2 Nếu có một đường đi từ s tới u qua nhiều nhất i cung, thì Khoảng_cách(u) có giá trị không vượt quá độ dài của đường đi ngắn nhất từ s tới u qua tối đa i cung Chứng minh
Trường hợp cơ bản: Xét i=0 và thời điểm trước khi vòng for được chạy lần đầu tiên Khi đó, với đỉnh nguồn khoảng_cách(nguồn) = 0, điều này đúng Đối với các đỉnh u khác, khoảng_cách(u) = vô cùng, điều này cũng đúng vì không có đường đi nào từ nguồn đến u qua 0 cung
Trường hợp quy nạp:
Chứng minh câu 1 Xét thời điểm khi khoảng cách tới một đỉnh được cập nhật bởi công thức khoảng_cách(v):= khoảng_cách(u) + trọng_số(u,v) Theo giả thiết quy nạp, khoảng_cách(u) là độ dài của một đường đi nào đó từ nguồn tới u Do đó, khoảng_cách(u) + trọng_số(u,v) là độ dài của đường đi từ nguồn tới u rồi tới v Chứng minh câu 2: Xét đường đi ngắn nhất từ nguồn tới u qua tối đa i cung Giả sử
v là đỉnh liền ngay trước u trên đường đi này Khi đó, phần đường đi từ nguồn tới v
là đường đi ngắn nhất từ nguồn tới v qua tối đa i-1 cung Theo giả thuyết quy nạp, khoảng_cách(v) sau i-1 vòng lặp không vượt quá độ dài đường đi này Do đó, trọng_số(v,u) + khoảng_cách(v) có giá trị không vượt quá độ dài của đường đi từ s tới u.Trong lần lặp thứ i, khoảng_cách(u) được lấy giá trị nhỏ nhất của
khoảng_cách(v) + trọng_số(v,u) với mọi v có thể Do đó, sau i lần lặp,
khoảng_cách(u) có giá trị không vượt quá độ dài đường đi ngắn nhất từ nguồn tới u qua tối đa i cung
Trang 7Khi i bằng số đỉnh của đồ thị, mỗi đường đi tìm được sẽ là đường đi ngắn nhất toàn cục, trừ khi đồ thị có chu trình âm Nếu tồn tại chu trình âm mà từ đỉnh nguồn có thể đi đến được thì sẽ không tồn tại đường đi nhỏ nhất (vì mỗi lần đi quanh chu trình âm là một lần giảm trọng số của đường)
2.2 Ứng dụng trong định tuyến
Một biến thể phân tán của thuật toán Bellman-Ford được dùng trong các giao thức định tuyến vector khoảng cách, chẳng hạn giao thức RIP (Routing Information Protocol) Đây là biến thể phân tán vì nó liên quan đến các nút mạng (các thiết bị định tuyến) trong một hệ thống tự chủ (autonomous system), ví dụ một tập các mạng IP thuộc sở hữu của một nhà cung cấp dịch vụ Internet (ISP)
Thuật toán gồm các bước sau:
1 Mỗi nút tính khoảng cách giữa nó và tất cả các nút khác trong hệ thống tự chủ và lưu trữ thông tinnày trong một bảng
2 Mỗi nút gửi bảng thông tin của mình cho tất cả các nút lân cận
3 Khi một nút nhận được các bảng thông tin từ các nút lân cận, nó tính các tuyến đường ngắn nhất tớitất cả các nút khác và cập nhật bảng thông tin của chính mình Nhược điểm chính của thuật toán Bellman-Ford trong cấu hình này là
• Không nhân rộng tốt
• Các thay đổi của tô-pô mạng không được ghi nhận nhanh do các cập nhật được lan truyền theo từngnút một
• Đếm dần đến vô cùng (nếu liên kết hỏng hoặc nút mạng hỏng làm cho một nút bị tách khỏi một tậpcác nút khác, các nút này vẫn sẽ tiếp tục ước tính khoảng cách tới nút đó và tăng dần giá trị tínhđược, trong khi đó còn có thể xảy ra việc định tuyến thành vòng tròn)
2.3.Sự ra đời của thuật toán ford-bellman
Thuật toán lần đầu tiên được đề xuất bởi Alfonso Shimbel (1955), nhưng thay vào
đó được đặt theo tên của Richard Bellman và Lester Ford Jr., những người đã xuất bản nó lần lượt vào năm 1958 và 1956
Thuật toán Bellman – Ford là một thuật toán tính toán các đường đi ngắn nhất từ một đỉnh nguồn duy nhất đến tất cả các đỉnh khác trong một đồ thị có trọng số Nó chậm hơn so với thuật toán Dijkstra cho cùng một vấn đề, nhưng linh hoạt hơn, vì
nó có khả năng xử lý các đồ thị trong đó một số trọng số cạnh là số âm Thuật toán này thường được đặt theo tên của hai nhà phát triển của nó, Richard Bellman và Lester Ford, Jr., những người đã xuất bản nó lần lượt vào năm 1958 và 1956; tuy nhiên, Edward F Moore cũng đã công bố thuật toán tương tự vào năm 1957, và vì
Trang 8lý do này, nó đôi khi còn được gọi là thuật toán Bellman – Ford – Moore Trọng số cạnh âm được tìm thấy trong các ứng dụng khác nhau của đồ thị, do đó tính hữu ích của thuật toán này Tuy nhiên, nếu một đồ thị chứa "chu trình âm", tức là một chu trình có các cạnh tổng bằng giá trị âm, thì không có đường đi nào rẻ nhất, bởi vì bất
kỳ đường đi nào cũng có thể rẻ hơn bằng cách thêm một lần đi qua chu trình âm Trong trường hợp như vậy, thuật toán Bellman – Ford có thể phát hiện các chu trình
âm và báo cáo sự tồn tại của chúng, nhưng nó không thể tạo ra câu trả lời chính xác
về "đường đi ngắn nhất" nếu có thể truy cập được chu trình âm từ nguồn
2.4 Mô tả thuật toán
function BellmanFord(danh_sách_đỉnh, danh_sách_cung, nguồn)
// hàm yêu cầu đồ thị đưa vào dưới dạng một danh sách đỉnh, một danh sách cung // hàm tính các giá trị khoảng_cách và đỉnh_liền_trước của các đỉnh,
// sao cho các giá trị đỉnh_liền_trước sẽ lưu lại các đường đi ngắn nhất
// bước 1: khởi tạo đồ thị
for each v in danh_sách_đỉnh:
if v is nguồn then khoảng_cách(v):= 0
else khoảng_cách(v):= vô cùng
đỉnh_liền_trước(v):= null
// bước 2: kết nạp cạnh
for i from 1 to size(danh_sách_đỉnh)-1:
for each (u,v) in danh_sách_cung:
if khoảng_cách(v) > khoảng_cách(u) + trọng_số(u,v):
khoảng_cách(v):= khoảng_cách(u) + trọng_số(u,v)
đỉnh_liền_trước(v):= u
// bước 3: kiểm tra chu trình âm
for each (u,v) in danh_sách_cung:
if khoảng_cách(v) > khoảng_cách(u) + trọng_số(u,v):
error "Đồ thị chứa chu trình âm"
2.5.Đánh giá thuật toán
Ưu điểm:
Giống Dijkstra, đây là thuật toán tìm đường ngắn nhất nhưng đại thể là có ưu điểm hơn là giải quyết được đồ thị chu trình âm
Trang 9Từ 1 đỉnh xuất phát nhìn hình ta có thế suy ra đường đi ngắn nhất từ đỉnh đó tới các đỉnh khác mà không cần làm lại từ đầu Rất gọn,dễ nhớ,dễ học
Nhược điểm:
Là đôi khi nó quét lại cả các nút đã quét nên hiệu suất không cao bằng Ở viễn thông thì không biết có trường hợp nào đường đi nào có giá trị âm nên mình cũng khó đánh giá
Cái kia mỗi lần quét thì thêm vào 1 giá trị nhỏ nhất vào tập hợp các đường đã biết, lần sau không phải quét nữa còn cái này cứ quét đại trà với vòng lặp bằng số đỉnh thì dừng
Tốn quá nhiều thời gian,độ phức tạp quá cao 0(n^3)
Trang 10CHƯƠNG 3 NỘI DUNG THỰC HÀNH
3.1.Giải thích cách hoạt động của ứng dụng giải thuật Prim bằng Windows Form:
Thuật toán xử lý chính ở hàm Calculate ở Form1.cs
(1)Danh sách các đỉnh được lưu ở listVertex
(2)Danh sách các cạnh ở listEdge
(3)Tạo listInTreeVertex - danh sách lưu các đỉnh trong cây khung nhỏ nhất Mỗi danh sách chúng ta tạo thêm danh sách copy để xử lý các đỉnh và cạnh
Ta đánh dấu mỗi đỉnh là chưa được duyệt
(4)Tạo đỉnh gốc được lấy từ comboboxRootVertex, đánh dấu đỉnh đã duyệt rồi (5)Tạo vòng lặp, chạy đến khi nào số đỉnh trong danh sách cây khung = (số đỉnh - 1) hoặc đã duyệt qua tất cả các đỉnh rồi
Với mỗi vòng lặp:
Tìm mỗi các đỉnh kề với cây khung
Tìm đỉnh có trọng số cạnh nhỏ nhất
Thêm vào cây khung nhỏ nhất, tăng số đỉnh trong cây khung lên 1
Đánh dấu đỉnh đã duyệt
Kết thúc vòng lặp ta có cây khung nhỏ nhất
Trang 113.2 Giải thích cách hoạt động của ứng dụng giải thuật Ford Bellman bằng Windows Form:
Thuật toán xử lý chính ở hàm bellmanFord ở FB.cs
Hàm tính các giá trị khoảng cách được lưu trong mảng khoangcach(1) và đỉnh liền
trước của các đỉnh được lưu trong mảng truoc(2).
Sao cho các giá trị đỉnh liền trước sẽ lưu lại các đường đi ngắn nhất
Ta thực hiện duyệt n lần, với n là số đỉnh của đồ thị
Với mỗi lần duyệt, ta tìm tất cả các cạnh mà đường đi qua cạnh đó sẽ rút ngắn đường đi ngắn nhất từ đỉnh gốc tới một đỉnh khác
Ở lần duyệt thứ n, nếu còn bất kỳ cạnh nào có thể rút ngắn đường đi, điều đó chứng
tỏ đồ thị có chu trình âm, và ta kết thúc thuật toán
Trang 12BẢNG PHÂN CÔNG CÔNG VIỆC
ST
T
4
Đọc hiểu code, tổng hợp và viết báo cáo minh họa
2 Trần Thanh Bình 46.01.104.01
4
Tổng hợp và hoàn chỉnh code, đọc hiểu code, quay video demo
3 Phạm Đức Tài 44.01.104.18
6
Tìm kiếm, tổng hợp, đọc hiểu và chỉnh sửa giao diện mỗi thuật toán
4 Đinh Trần Thanh
Tú
46.01.104.20 5
Tìm kiếm, tổng hợp, đọc hiểu và chỉnh sửa giao diện mỗi thuật toán
5 Trương Thế Nhật 46.01.104.12
9
(Không có máy tính hỗ trợ) theo dõi các thành viên trong nhóm để nắm được kiến thức của thuật toán
Tự đánh giá:
Các thuật toán nhóm thực hiện chỉ có thể áp dụng với đồ thị vô hướng, chưa thể áp dụng với đồ thị có hướng Nhóm chưa biết cách gộp các project lại mà chỉ có thể chạy
2 project trên cùng 1 solution