Đây là lĩnh vực đang được các nhà khoa học quan tâm nghiên cứu.Trong bối cảnh hiện tại, thuật toán tìm luồng cực đại trên mạng cần được nghiên cứu và cải tiến theo hướng song song nhằm p
Trang 2LỜI CAM ĐOAN
Tôi xin cam đoan:
1 Đây là công trình nghiên cứu của riêng tôi
2.Các số liệu, các kết quả nêu trong luận văn là trung thực và chưa từng được ai công
bố trong bất kì công trình nào khác
Tác giả
Hồ Xuân Bình
Trang 3MỤC LỤC
Lời cam đoan i
Mục lục ii
Danh mục các bảng biểu iv
Danh mục các hình vẽ v
Mở đầu vii
Nội dung 1
Chương1 TỔNG QUAN 1
1.1.Mạng 1
1.1.1.Các khái niệm cơ bản của lý thuyết đồ thị 1
1.1.2 Mạng 9
1.1.3 Luồng trong mạng 9
1.1.4 Luồng cực đại, lát cắt cực tiểu 10
1.1.5.Mạng tổng quát 12
1.1.6 Mạng với nhiều điểm phát và điểm thu 13
1.1.7.Biểu diễn đồ thị trên máy tính 14
1.2 Lập trình song song và phân tán 20
1.2.1 Giới thiệu về lập trình song song 20
1.2.2 Các mô hình lập trình song song 23
1.2.3 Thuật toán song song 34
Chương 2 THUẬT TOÁN TÌM LUỒNG CỰC ĐẠI TRÊN MẠNG 38
2.1 Thuật toán truyền thống 39
2.2 Thuật toán hoán chuyển nguồn đích có trọng số tìm luồng cực đại 43
2.3.Thuật toán song song tìm luồng cực đại trên mạng……… 47
Chương 3 ỨNG DỤNG CỦA MẠNG 57
Trang 43.1.Cài đặt và Demo chương trình 57
3.2 Ứng dụng trong lý thuyết tổ hợp 64
3.3 Ứng dụng trong thực tế 68
Kết luận và hướng phát triển 73
Tài liệu tham khảo 75
Trang 5
DANH MỤC CÁC BẢNG BIỂU
Bảng 3.1 Test1input.txt 60 Bảng 3.2 Test1output.txt 62 Bảng 3.3 Bảng phân công đề tài tốt nghiệp 68
Trang 6DANH MỤC CÁC HÌNH VẼ
Hình 1.1 Một số hình ảnh về đồ thị 2
Hình 1.2 Đồ thị vô hướng 2
Hình 1.3 Đồ thị có hướng 3
Hình 1.4 Minh hoạ đồ thị vô hướng 4
Hình 1.5 Minh hoạ đồ thị có hướng 5
Hình 1.6 Đồ thị đầy đủ 6
Hình 1.7 Đồ thị lưỡng phân 7
Hình 1.8 Trọng đồ 8
Hình 1.9 Mạng 9
Hình 1.10 Biểu diễn luồng trên mạng 10
Hình 1.11 Mạng tổng quát 13
Hình 1.12 Mạng với nhiều điểm phát, điểm thu 14
Hình 1.13 Ma trận kề 14
Hình 1.14 Minh hoạ đồ thị 16
Hình 1.15 Cài đặt danh sách móc nối 16
Hình 1.16 Minh hoạ đồ thị 17
Hình 1.17 Dùng một mảng các đỉnh 17
Hình 1.18 Danh sách móc nối 18
Hình 1.19 Mô hình lập trình song song 20
Hình 1.20 Sơ đồ trạng thái của Thread 26
Hình 1.21 Mô hình triệu gọi các đối tượng từ xa 29
Hình 1.22 Gọi phương thức của đối tượng thông qua lớp trung gian 30
Hình 1.23 Sự trao đổi thông điệp giữa các máy tính trong hệ PVM 32
Hình 2.1 Sơ đồ thuật toán tuần tự tìm luồng cực đại trên mạng 40
Trang 7Hình 2.2 Mô phỏng ý tưởng thuật toán song song 47
Hình 2.3 Mô hình Client, Server 48
Hình 2.4 Sơ đồ thuật toán song song tìm luồng cực đại trên mạng 55
Hình 2.5 Cơ sở dữ liệu mạng 55
Hình 3.1 Sơ đồ cài đặt chương trình Demo 58
Hình 3.2 Giao diện Server 59
Hình 3.3 Giao diện Client 59
Hình 3.4 Giao diện bộ test1 62
Hình 3.5 Dữ liệu nhập từ đồ thị 63
Hình 3.6 Kết quả xuất ra đồ thị 63
Hình 3.7 Mạng tương ứng với bài toán phân đề tài tốt nghiệp 68
Hình 3.8 Hình ảnh vận chuyển hàng 69
Hình 3.9 Mạng vận chuyển hàng 70
Hình 3.10 Hình ảnh vận chuyển dầu 71
Hình 3.11 Mạng tổng quát vận chuyển dầu 72
Trang 8MỞ ĐẦU
1.1 Lý do chọn đề tài
Ngày nay, lĩnh vực toán ứng dụng trong tin học đã trở nên phát triển mạnh mẽ Toán học là nền tảng của tin học, cơ sở toán học và tư duy toán học là hai yếu tố quan trọng
hỗ trợ đắc lực trong lĩnh vực tin học.Vai trò của toán học ngày một khẳng định hơn khi
có sự ra đời của bộ môn toán ứng dụng trong tin học.Trong đó, vấn đề mạng, bài toán luồng cực đại và lát cắt cực tiểu trên mạng là một điển hình Lý thuyết mạng, bài toán luồng cực đại trên mạng là cơ sở khoa học để giải quyết các bài toán đặt ra trong giải tích tổ hợp cũng như trong thực tế Nó thực sự có một vai trò quan trọng trong việc giải quyết những vấn đề đặt ra trong cuộc sống, đem lại những ứng dụng mạnh mẽ Đây là lĩnh vực đang được các nhà khoa học quan tâm nghiên cứu.Trong bối cảnh hiện tại, thuật toán tìm luồng cực đại trên mạng cần được nghiên cứu và cải tiến theo hướng song song nhằm phát huy sức mạnh của bài toán đồng thời bài toán cần được nhân rộng miền ứng dụng trong lý thuyết tổ hợp cũng như trong đời sống thực tế
Xuất phát từ tình hình thực tiễn trên, tôi chọn đề tài làm luận văn tốt nghiệp cao học:
Thuật toán tìm luồng cực đại trên mạng và ứng dụng
1.2 Mục tiêu và nhiệm vụ
Mục đích của đề tài: Đề xuất thuật toán song song tìm luồng cực đại trên mạng từ đó
xây dựng các ứng dụng thực tiễn
Nhiệm vụ:
- Tìm hiểu lý thuyết mạng, lập trình song song và phân tán
- Tìm hiểu thuật toán tìm luồng cực đại trên mạng
- Xây dựng thuật toán mới
- Xây dựng các ứng dụng
Trang 9Luận văn tập trung nghiên cứu lý thuyết, xây dựng mô hình, triển khai thực nghiệm, phân tích, đánh giá kết quả, từ đó đề xuất giải pháp tổng quát
1.3 Đối tượng và phạm vi nghiên cứu
- Lý thuyết tổng quan về đồ thị, mạng, lập trình song song và phân tán
- Cách biểu diễn đồ thị trên máy tính
- Thuật toán giải bài toán tìm luồng cực đại trên mạng
1.4 Giả thuyết nghiên cứu
Lý thuyết đồ thị, toán rời rạc, lập trình song song và phân tán
Đồ thị thuộc loại hình nghiên cứu: lý thuyết + ứng dụng
1.5 Phương pháp nghiên cứu
Kết hợp lý thuyết + lập trình thực nghiệm nhằm xây dựng thuật toán tìm luồng cực đại trên mạng, thuật toán được cài đặt bằng ngôn ngữ lập trình Java
Đề tài được thực hiện theo tiến trình sau:
- Thu thập, phân tích tài liệu liên quan đến đề tài
- Nghiên cứu, lựa chọn phương pháp giải quyết vấn đề đặt ra
- Triển khai xây dựng ứng dụng thực tiễn
- Kiểm tra thử nghiệm và đánh giá kết quả đem lại
1.6 Ý nghĩa khoa học và thực tiễn của đề tài
- Cơ sở phát triển lý thuyết mạng
- Cơ sở phát triển lập trình song song
- Tài liệu phục vụ cho việc dạy học
- Ứng dụng trong lý thuyết tổ hợp và trong thực tế
Trang 10Phần nội dung:
Chương 1 Tổng quan
Trình bày lý thuyết đồ thị, lý thuyết mạng, lập trình song song và phân tán
Chương 2 Thuật toán tìm luồng cực đại trên mạng
Phát biểu bài toán, trình bày thuật toán truyền thống, thuật toán hoán chuyển nguồn đích, từ đó thiết kế thuật toán song song tìm luồng cực đại trên mạng
Chương 3 Ứng dụng của mạng
Ghi nhận kết quả Demo chương trình cài đặt thuật toán song song, nêu lên các ứng dụng của mạng trong lý thuyết tổ hợp và những ứng dụng quan trọng trong thực tế
Kết luận và hướng phát triển: Trình bày đánh giá các kết quả đạt được, những vấn đề
còn hạn chế từ đó đề xuất hướng nghiên cứu tiếp theo của đề tài
Trang 111.1.1.Các khái niệm cơ bản của lý thuyết đồ thị
Lý thuyết đồ thị là một lĩnh vực nghiên cứu đã có từ lâu và có nhiều ứng dụng hiện đại Những tư tưởng cơ bản của lý thuyết đồ thị được đề xuất vào những năm đầu của thế kỷ
18 bởi nhà toán học lỗi lạc người Thụy Sĩ Leonhard Euler Chính ông là người đã sử dụng đồ thị để giải quyết bài toán về 7 cây cầu ở thành phố Konuysberg
1.1.1.1 Định nghĩa đồ thị
Đồ thị là một cấu trúc rời rạc bao gồm các đỉnh và các cạnh nối với các đỉnh ấy Được
mô tả dưới hình thức G=(V,E) Trong đó V(Vertices) là tập hợp các đỉnh và E(Edges)
là tập hợp các cạnh của đồ thị Có thể xem E là tập hợp các cạnh (u,v) trong đó u,v là các đỉnh thuộc V
Hình 1.1 minh họa một số hình ảnh về đồ thị
Trang 12Đồ thị vô hướng G = (V,E) gồm một tập V các đỉnh và tập E các cạnh trong đó mỗi
cạnh e được liên kết với một cặp đỉnh u,v trong V( không kể thứ tự )
6
Hình 1.1: Một số hình ảnh về đồ thị
Hình 1.2: Đồ thị vô hướng
Trang 13Đồ thị có hướng G = (V,E) gồm một tập V các đỉnh và tập E các cạnh có hướng trong
đó mỗi cạnh e được liên kết với một cặp đỉnh u,v trong V( có thứ tự )
6
Cho đồ thị G(V,E)
Nếu cạnh e liên kết với đỉnh u, v thì ta nói e là cạnh liên thuộc hai đỉnh u, v và hai đỉnh
u, v được gọi là biên của cạnh e; u, v là hai đỉnh kề nhau
Cạnh có hai đỉnh liên kết trùng nhau gọi là khuyên
Nếu có nhiều cạnh liên kết với cùng một cặp đỉnh thì ta gọi các cạnh ấy là song song với nhau
Đỉnh không có đỉnh kề gọi là đỉnh cô lập
Số đỉnh của đồ thị gọi là bậc của đồ thị
Số cạnh của đồ thị gọi là cỡ của đồ thị
Đồ thị hữu hạn là đồ thị có bậc và cỡ hữu hạn
Đồ thị đơn là đồ thị không có khuyên và không có cạnh song song
Bậc, nửa bậc vào, nửa bậc ra
Cho đồ thị G(V,E)
Bậc của đỉnh v là tổng số cạnh liên thuộc đến nó Kí hiệu: d(v)
Công thức tính bậc: d(v) = số cạnh liên thuộc v + 2*số khuyên
Hình 1.3: Đồ thị có hướng
Trang 14Từ công thức ta suy ra: v là đỉnh cô lập khi chỉ khi d(v) = 0
Đỉnh treo là đỉnh có bậc bằng 1
Cho G(V,E) là đồ thị có hướng
Nữa bậc ra của đỉnh v ( kí hiệu là do(v) ) là tổng số cung đi ra từ đỉnh v Nữa bậc vào của đỉnh v ( kí hiệu là di(v) ) là tổng số cung đi vào đỉnh v
Trang 15Trong đồ thị này ta có:
di(1)=1; di(2) = 2; di(3) = 1; di(4) = 0; di(5) = 1; di(6) = 0;
do(1)=1; do(2) = 0; do(3) = 1; do(4) = 3; do(5) = 0; do(6) = 0;
Bổ đề bắt tay( Hand Shaking Lemma )
Cho đồ thị vô hướng G(V,E) Khi đó:
i) Tổng số bậc của đồ thị là số chẵn và d(v) 2.card(E)
V v
ii) Nếu G là đồ thị có hướng thì
Trang 161
45
3
Hình 1.6: Đồ thị đầy đủ
Mệnh đề : Mọi đỉnh của đồ thị Kn có bậc n -1 và Kn có n(n-1)/2 cạnh
Đồ thị lưỡng phân G(V,E) là đồ thị mà tập các đỉnh được phân làm 2 tập rời nhau V1,
V2 sao cho bất kì cạnh e=(u,v) của đồ thị ta có uV1,vV2
Kí hiệu: G=({V1, V2}, E )
Đồ thị Km,n là đồ thị lưỡng phân({V1, V2},E ) với tập V1 có m đỉnh và tập V2 có n đỉnh
và với mỗi đỉnh của V1 được nối với mỗi đỉnh của V2 bằng duy nhất một cạnh
Hình 1.7 biểu diễn đồ thị lưỡng phân K3,4
x
Hình 1.7: Đồ thị lưỡng phân
Trang 17Mệnh đề: Cho đồ thị Km,n là đồ thị lưỡng phân ({V1, V2},E) với tập V1 có m đỉnh và tập V2 có n đỉnh khi đó mỗi đỉnh trong V1 có bậc là n và mỗi đỉnh trong V2 có bậc là m
và đồ thị có m.n cạnh
Đường đi, chu trình, tính liên thông
Định nghĩa: Cho đồ thị G(V,E)
Dãy p từ đỉnh u đến đỉnh v là dãy các đỉnh và các cạnh nối tiếp nhau từ đỉnh u đến đỉnh
v Số cạnh trên dãy p được gọi là độ dài của dãy p
Dãy p được biểu diễn như sau:
P = (u, e1,v1,…….,en-1,vn-1,en,v)
Đường đi từ u đến v là dãy từ đỉnh u đến v sao cho các cạnh không lặp lại
Đường đi sơ cấp là đường đi sao cho không đi qua mỗi đỉnh quá một lần
Vòng là dãy có đỉnh đầu và đỉnh cuối trùng nhau
Chu trình là đường đi có đỉnh đầu và đỉnh cuối trùng nhau
Chu trình sơ cấp là chu trình không đi qua mỗi đỉnh quá một lần
Dãy có hướng trong đồ thị có hướng là dãy các đỉnh và các cung nối tiếp nhau
(e1,e2,……….,en) thỏa mãn đỉnh cuối cùng của ei là đỉnh đầu của cung ei+1 , i= 1 n-1 Đường đi có hướng trong đồ thị có hướng là dãy có hướng, trong đó các cung không lặp lại
Đường đi có hướng sơ cấp là đường đi có hướng không đi qua mỗi đỉnh quá một lần Vòng có hướng là dãy có hưỡng với đỉnh đầu và đỉnh cuối trùng nhau
Chu trình có hướng là đường đi có hướng với đỉnh đầu và đỉnh cuối trùng nhau
Chu trình có hướng sơ cấp là chu trình có hướng không đi qua mỗi đỉnh quá một lần
Đồ thị vô hướng gọi là liên thông, nếu mọi cặp đỉnh của nó đều có đường đi nối chúng với nhau
Đồ thị có hướng gọi là liên thông mạnh, nếu mọi cặp đỉnh của nó đều có đường đi có hướng nối chúng với nhau
Trang 18Đồ thị có hướng gọi là liên thông yếu, nếu đồ thị lót của chúng(đồ thị vô hướng) liên thông
Đồ thị có hướng gọi là bán liên thông, nếu mọi cặp đỉnh (u,v) bao giờ cũng tồn tại đường đi có hướng từ u đến v hoặc từ v đến u
Trọng đồ ( có hướng ) là đồ thị( có hướng ) mà mỗi cạnh của nó được gán một số Trọng đồ được biểu diễn bởi: G = (V,E, w) trong đó V: tập các đỉnh, E: tập các cạnh, w:
là trọng số của cạnh( cung ) e với mọi e thuộc E
Trong trọng đồ, độ dài trọng số của đường đi p là tổng các trọng số trên đường đi đó Hình 1.8 mô phỏng trọng đồ
1
54
6
4
5
7 2
8
9
1 3
1.1.2 Mạng
Định nghĩa
Ta gọi mạng là đồ thị có hướng G(V,E,C) thỏa các điều kiện sau:
(1) Có duy nhất một đỉnh gọi là nguồn, không liên thuộc cung vào
(2) Có duy nhất một đỉnh gọi là đích, không liên thuộc cung ra
(3) Khả năng thông qua của cung : cij là các số không âm
(4) Đồ thị liên thông yếu
Ví dụ: Đồ thị trên hình 1.9 là mạng
Hình 1.8: Trọng đồ
Trang 19ed
10
18 4
k i
ik f f
) , ( ) , (
10(4)
18(6) 4(1)
Trang 20i a
ai f f
) , ( ) , (
i
ij f f
i ia V
i zi V
i iz z
a
V
ji V
, (
i a
ai f f
Định nghĩa giá trị của luồng :
G i a ai
f f
v
) , (
)(
1.1.4 Luồng cực đại, lát cắt cực tiểu
S c
| ij
cT)
,(
Lát cắt cực tiếu là lát cắt có khả năng thông qua nhỏ nhất
f T
S
f
|
),(
Định lý 1
Cho mạng G(V,E,c) với nguồn a, đích z f là luồng, (S,T) là lát cắt của G, khi đó:
Trang 21j i T
ji S
j i S
ij S
j i S
ji S
j i T ij S
j i S
ji
S
j i V ij S
j i V
ji V
i ai
f f
f f
f f
f f
f f
f f
j i T
ji c c S T f
T S f S T f T S f f
Định lý 3
Cho mạng G(V,E,c) khi đó:
(1) nếu v(f) = c(S,T) thì luồng f đạt giá trị cực đại và lát cắt (S,T) đạt giá trị cực tiểu (2) Đẳng thức v(f) = c(S,T) xảy ra khi chỉ khi
Trang 22Ta gọi mạng tổng quát là đồ thị có hướng G(V,E,c) thoả các điều kiện sau:
(1) Có duy nhất một đỉnh gọi là nguồn, không liên thuộc cung vào
(2) Có duy nhất một đỉnh gọi là đích, không liên thuộc cung ra
(3) Khả năng thông qua của cung : cij là các số không âm
(4)Khả năng thông qua của các đỉnh: ci là các số không âm
(5) Đồ thị liên thông yếu
Ví dụ: Đồ thị trên hình 1.11 là mạng tổng quát
a
ed
k kj G
k i
f
) , ( ) , (
f f
v
) , (
)(
Lát cắt tổng quát
Tập X gồm một số cạnh và một số đỉnh gọi là lát cắt tổng quát của G nếu mọi đường đi
có hướng từ đỉnh nguồn đến đỉnh đích đều phải chứa ít nhất một phần tử của X
Hình 1.11: Mạng tổng quát
Trang 231.1.6 Mạng với nhiều điểm phát và điểm thu
Xét mạng G với n điểm phát a1,a2,… an và m điểm thu z1, z2, ……zm Giả sử rằng có thể đi từ một điểm phát bất kỳ đến tất cả các điểm thu Bài toán tìm luồng cực đại từ các điểm phát đến các điểm thu có thể đưa về bài toán với một điểm phát và một điểm thu bằng cách tạo ra một điểm phát giả a và một điểm thu giả z, các cạnh nối a với tất cả các điểm phát và các cạnh nối các điểm thu với z
aij = 1 nếu (i, j) E
aij = 0 nếu (i, j) E
Quy ước aii = 0 với i;
Đối với đa đồ thị thì việc biểu diễn cũng tương tự như trên, chỉ có điều nếu như (i, j) là cạnh thì không phải ta ghi số 1 vào vị trí aij mà là ghi số cạnh nối giữa đỉnh i và đỉnh j
Hình 1.12: Mạng với nhiều điểm phát, điểm thu
Trang 24Các tính chất của ma trận kề
Đối với đồ thị vô hướng G, thì ma trận kề tương ứng là ma trận đối xứng (aij = aji), điều này không đúng với đồ thị có hướng
Nếu G là đồ thị vô hướng và A là ma trận kề tương ứng thì trên ma trận A:
Tổng các số trên hàng i = Tổng các số trên cột i = Bậc của đỉnh i = deg(i)
Nếu G là đồ thị có hướng và A là ma trận kề tương ứng thì trên ma trận A:
Tổng các số trên hàng i = nửa bậc ra của đỉnh i = deg+(i)
Tổng các số trên cột i = nửa bậc vào của đỉnh i = deg-(i)
Trong trường hợp G là đơn đồ thị, ta có thể biểu diễn ma trận kề A tương ứng là các phần tử logic
aij = TRUE nếu (i, j) E và aij = FALSE nếu (i, j) E
Ưu điểm của ma trận kề
Đơn giản, trực quan, dễ cài đặt trên máy tính
Để kiểm tra xem hai đỉnh (u, v) của đồ thị có kề nhau hay không, ta chỉ việc kiểm tra bằng một phép so sánh: auv ≠ 0
Nhược điểm của ma trận kề
Bất kể số cạnh của đồ thị là nhiều hay ít, ma trận kề luôn luôn đòi hỏi n2 ô nhớ để lưu các phần tử ma trận, điều đó gây lãng phí bộ nhớ dẫn tới việc không thể biểu diễn được
đồ thị với số đỉnh lớn
Với một đỉnh u bất kỳ của đồ thị, nhiều khi ta phải xét tất cả các đỉnh v khác kề với nó, hoặc xét tất cả các cạnh liên thuộc với nó Trên ma trận kề việc đó được thực hiện bằng cách xét tất cả các đỉnh v và kiểm tra điều kiện auv ≠ 0 Như vậy, ngay cả khi đỉnh u là
đỉnh cô lập( không kề với đỉnh nào ) hoặc đỉnh treo( chỉ kề với 1 đỉnh ) ta cũng buộc
phải xét tất cả các đỉnh và kiểm tra điều kiện trên dẫn tới lãng phí thời gian
1.1.7.2 Danh sách cạnh
Hình 1.13: Ma trận kề
Trang 25Trong trường hợp đồ thị có n đỉnh, m cạnh, ta có thể biểu diễn đồ thị dưới dạng danh sách cạnh bằng cách liệt kê tất cả các cạnh của đồ thị trong một danh sách, mỗi phần tử của danh sách là một cặp (u, v) tương ứng với một cạnh của đồ thị ( Trong trường hợp
đồ thị có hướng thì mỗi cặp (u, v) tương ứng với một cung, u là đỉnh đầu và v là đỉnh cuối của cung ) Danh sách được lưu trong bộ nhớ dưới dạng mảng hoặc danh sách móc nối Ví dụ với đồ thị ở Hình 1.14 :
Cài đặt trên mảng:
Cài đặt trên danh sách móc nối:
Ưu điểm của danh sách cạnh
Trong trường hợp đồ thị thưa(có số cạnh tương đối nhỏ: chẳng hạn m < 6n), cách biểu diễn bằng danh sách cạnh sẽ tiết kiệm được không gian lưu trữ, bởi nó chỉ cần 2m ô nhớ để lưu danh sách cạnh
Trong một số trường hợp, ta phải xét tất cả các cạnh của đồ thị thì cài đặt trên danh sách cạnh làm cho việc duyệt các cạnh dễ dàng hơn( Thuật toán Kruskal chẳng hạn )
Hình 1.14: Minh hoạ đồ thị
Hình 1.15: Cài đặt danh sách móc nối
Trang 26Nhược điểm của danh sách cạnh
Nhược điểm cơ bản của danh sách cạnh là khi ta cần duyệt tất cả các đỉnh kề với đỉnh v nào đó của đồ thị, thì chẳng có cách nào khác là phải duyệt tất cả các cạnh, lọc ra những cạnh có chứa đỉnh v và xét đỉnh còn lại Điều đó khá tốn thời gian trong trường hợp đồ thị dày( nhiều cạnh )
1.1.7.3 Danh sách kề
Để khắc phục nhược điểm của các phương pháp ma trận kề và danh sách cạnh, người ta
đề xuất phương pháp biểu diễn đồ thị bằng danh sách kề Trong cách biểu diễn này, với mỗi đỉnh v của đồ thị, ta cho tương ứng với nó một danh sách các đỉnh kề với v
Với đồ thị G = (V, E) V gồm n đỉnh và E gồm m cạnh Có hai cách cài đặt danh sách
kề phổ biến:
Cách 1: Dùng một mảng các đỉnh, mảng đó chia làm n đoạn, đoạn thứ i trong mảng lưu
danh sách các đỉnh kề với đỉnh i: Với đồ thị ở Hình 1.16, danh sách kề sẽ là một mảng
A gồm 12 phần tử:
Để biết một đoạn nằm từ chỉ số nào đến chỉ số nào, ta có một mảng Head lưu vị trí riêng Head[i] sẽ bằng chỉ số đứng liền trước đoạn thứ i Quy ước Head[n + 1] bằng m Với đồ thị bên thì mảng
Hình 1.16: Minh hoạ đồ thị
Hình 1.17: Dùng một mảng các đỉnh
Trang 27Head[1 6] sẽ là: (0, 3, 5, 8, 10, 12)
Trong mảng A, đoạn từ vị trí Head[i] + 1 đến Head[i + 1] sẽ chứa các đỉnh kề với đỉnh
i Lưu ý rằng với đồ thị có hướng gồm m cung thì cấu trúc này cần phải đủ chứa m phần
tử, với đồ thị vô hướng m cạnh thì cấu trúc này cần phải đủ chứa 2m phần tử
Cách 2: Dùng các danh sách móc nối: Với mỗi đỉnh i của đồ thị, ta cho tương ứng với
nó một danhsách móc nối các đỉnh kề với i, có nghĩa là tương ứng với một đỉnh i, ta phải lưu lại List[i] là chốt của một danh sách móc nối Ví dụ với đồ thị ở Hình 1.16, các danh sách móc nối sẽ là:
Ưu điểm của danh sách kề
Đối với danh sách kề, việc duyệt tất cả các đỉnh kề với một đỉnh v cho trước là hết sức
dễ dàng, cái tên "danh sách kề" đã cho thấy rõ điều này Việc duyệt tất cả các cạnh cũng đơn giản vì một cạnh thực ra là nối một đỉnh với một đỉnh khác kề nó
Hình 1.18: Danh sách móc nối
Trang 28Nhược điểm của danh sách kề
Danh sách kề yếu hơn ma trận kề ở việc kiểm tra (u, v) có phải là cạnh hay không, bởi trong cách biểu diễn này ta sẽ phải việc phải duyệt toàn bộ danh sách kề của u hay danh sách kề của v Tuy nhiên đối với những thuật toán mà ta sẽ khảo sát, danh sách kề tốt hơn hẳn so với hai phương pháp biểu diễn trước Chỉ có điều, trong trường hợp cụ thể
mà ma trận kề hay danh sách cạnh không thể hiện nhược điểm thì ta nên dùng ma trận
kề( hay danh sách cạnh ) bởi cài đặt danh sách kề có phần dài dòng hơn
Nhận xét
Trên đây là nêu các cách biểu diễn đồ thị trong bộ nhớ của máy tính, còn nhập dữ liệu cho đồ thị thì có nhiều cách khác nhau, dùng cách nào thì tuỳ Chẳng hạn nếu biểu diễn bằng ma trận kề mà cho nhập dữ liệu cả ma trận cấp n x n (n là số đỉnh) thì khi nhập từ bàn phím sẽ rất mất thời gian, ta cho nhập kiểu danh sách cạnh cho nhanh Chẳng hạn mảng A (nxn) là ma trận kề của một đồ thị vô hướng thì ta có thể khởi tạo ban đầu mảng A gồm toàn số 0, sau đó cho người sử dụng nhập các cạnh bằng cách nhập các cặp (i, j); chương trình sẽ tăng A[i, j] và A[j, i] lên 1 Việc nhập có thể cho kết thúc khi người sử dụng nhập giá trị i = 0
Trong nhiều trường hợp đủ không gian lưu trữ, việc chuyển đổi từ cách biểu diễn nào
đó sang cách biểu diễn khác không có gì khó khăn Nhưng đối với thuật toán này thì làm trên ma trận kề ngắn gọn hơn, đối với thuật toán kia có thể làm trên danh sách cạnh
dễ dàng hơn v.v… Do đó, với mục đích dễ hiểu, các chương trình sau này sẽ lựa chọn phương pháp biểu diễn sao cho việc cài đặt đơn giản nhất nhằm nêu bật được bản chất thuật toán Còn trong trường hợp cụ thể bắt buộc phải dùng một cách biểu diễn nào đó khác, thì việc sửa đổi chương trình cũng không tốn quá nhiều thời gian
1.2 Lập trình song song và phân tán
1.2.1 Giới thiệu về lập trình song song
Lý thuyết về xử lý song song (parallel processing) bắt đầu cuối những năm 1940 khi J.Von Neumann giới thiệu một số mô hình hạn chế của tính toán song song có tên otomat tế bào mà chủ yếu là một mảng hai chiều các bộ xử lý trạng thái hữu hạn được
Trang 29tương kết theo dạng hình lưới Từ đó đến nay, lý thuyết về xử lý song song trở thành lĩnh vực nghiên cứu quan trọng và ngày càng đem lại những dấu hiệu khả quan trong việc xây dựng một mô hình lập trình mới có những tính năng vượt trội so với mô hình
lập trình tuần tự truyền thống
Hình 1.19: Mô hình lập trình song song
Tại sao phải xử lý song song?
Nhiều lĩnh vực mới như đồ họa máy tính, trí tuệ nhận tạo, phân tích số, v.v đòi hỏi phải
xử lý một khối lượng dữ liệu rất lớn, những vấn đề về xử lý ngôn ngữ tự nhiên, nhận dạng, xử lý ảnh ba chiều( 3-D ), dự báo thời tiết v.v đều đòi hỏi phải xử lý dữ liệu với tốc độ rất cao, với khối lượng dữ liệu rất lớn Hầu hết những bài toán này, những máy tính xử lý tuần tự là không đáp ứng yêu cầu thực tế Do đó cần phải có những hệ thống máy tính thật mạnh mới đáp ứng được những yêu cầu thực tế đặt ra
Mặc dù tốc độ xử lý của các bộ xử lý tăng nhiều trong những năm qua, nhưng do giới hạn về vật lý nên khả năng tính toán của chúng không thể tăng mãi được Điều này dẫn tới là muốn tăng được khả năng tính toán của các hệ thống máy tính thì đích cuối cùng
là phải khai thác được khả năng xử lý song song của chúng
Trang 30Ngày càng xuất hiện nhiều bài toán mà những hệ thống đơn một bộ xử lý không đáp ứng được yêu cầu xử lý về thời gian, do đó đòi hỏi phải sử dụng những hệ thống đa bộ
xử lý và đòi hỏi phải xử lý song song
Khái niệm
Xử lý song song là quá trình xử lý gồm nhiều tiến trình được kích hoạt đồng thời và cùng tham gia giải quyết một vấn đề, nói chung là thực hiện trên những hệ thống đa bộ
xử lý
Sự khác biệt giữa xử lý song song và xử lý tuần tự
Trong tính toán song song, một số bộ xử lý cùng kết hợp với nhau để giải quyết cùng một vấn đề cho nên giảm được thời gian xử lý vì mỗi thời điểm có thể có nhiều phép toán được thực hiện đồng thời
Trong tính toán tuần tự với một bộ xử lý thì mỗi thời điểm chỉ thực hiện được một phép toán
Mục đích của xử lý song song là tận dụng các khả năng của các hệ đa bộ xử lý để thực hiện những tính toán nhanh hơn trên cơ sở sử dụng nhiều bộ xử lý đồng thời Cùng với tốc độ xử lý nhanh hơn, việc xử lý song song cũng sẽ giải quyết được những bài toán lớn hơn
Xử lý song song thực hiện dựa trên ba yếu tố sau:
Sự phát triển của công nghệ mạch tích hợp VLSI cho phép tạo ra những hệ phức hợp
có hàng triệu transistor trên một chip
Hiện nay giá thành của phần cứng giảm mạnh, tạo điều kiện để xây dựng những hệ thống có nhiều bộ xử lý với giá thành hợp lý
Tốc độ xử lý của các bộ xử lý theo kiểu von Neumann đã dần tiến tới giới hạn, không thể cải tiến thêm được do vậy dẫn tới đòi hỏi phải thực hiện xử lý song song
Những yếu tố trên thúc đẩy các nhà nghiên cứu phải tập trung khai thác công nghệ xử
lý song song và tận dụng chúng để giải quyết những bài toán đặt ra
Vấn đề xử lý song song liên quan trực tiếp đến kiến trúc máy tính, phần mềm hệ thống, thuật toán và ngôn ngữ lập trình, v.v
Trang 31Một máy tính song song là tuyển tập các bộ xử lý, thường là cùng một loại, kết nối với nhau theo một kiến trúc topo xác định để có thể hợp tác với nhau trong hoạt động và trao đổi dữ liệu được với nhau
Phần lớn các hệ điều hành ngày nay đều đã hỗ trợ đa xử lý, đa nhiệm và cho phép nghiên cứu, khai thác các phương pháp lập trình song song Vấn đề là chúng ta phải có nhiều Bộ xử lý( các đơn vị tính toán độc lập ) cùng hoạt động Nhưng điều quan trọng của xử lý song song là các bộ xử lý phải cùng tham gia " giải một bài toán" Nói cách khác, những tiến trình thực hiện trên mỗi bộ xử lý phải kết hợp, trao đổi với nhau để giải quyết bài toán đặt ra
Ví dụ: Ta xét bài toán tìm phần tử a trên mảng A kích thước n
Trong xử lý tuần tự, ta dùng một bộ xử lý duyệt từ phần tử đầu đến phần tử cuối của mảng
Trong xử lý song song, giả sử ta có một mô hình song song m bộ xử lý, ta chia việc cho mỗi bộ xử lý đồng thực hiện tìm kiếm, một bộ xử lý tìm kiếm trên (n div m) phần tử Trong quá trình thực hiện, bộ xử lý nào tìm thấy phần tử a hoặc đã duyệt qua hết rồi nhưng không tìm thấy thì phải gửi thông điệp để hệ thống xử lý nhận biết, điều khiển quá trình xử lý
Trang 32Chúng ta dễ nhận thấy là độ phức tạp của xử lý song song có thể sẽ lớn hơn xử lý tuần
tự rất nhiều, bởi vì cần có sự trao đổi thông tin và sự đồng bộ các tiến trình trong quá trình thực hiện xử lý bài toán, vấn đề chúng ta cần quan tâm ở đây chính là thời gian thực hiện chương trình
Một trong những mục đích chính của xử lý song song là nghiên cứu, xây dựng những thuật toán thích hợp để cài đặt trên các máy tính song song, nghĩa là phát triển các thuật toán song song nhằm giải quyết các bài toán đặt ra trong thực tế
Vấn đề đặt ra là đánh giá một thuật toán song song như thế nào được gọi là thích hợp? Trong thuật toán tuần tự thì chúng ta đánh giá dựa vào thời gian thực hiện thuật toán, không gian bộ nhớ và khả năng lập trình, v.v Đánh giá thuật toán song song thì phức tạp hơn nhiều, ngoài những tiêu chuẩn trên còn phải bổ sung thêm các thông số về số
bộ xử lý, khả năng của các bộ nhớ cục bộ, sơ đồ truyền thông, và các giao thức đồng bộ hoá tiến trình v.v
1.2.2 Các mô hình lập trình song song
1.2.2.1 Lập trình chia sẻ bộ nhớ
Lập trình chia sẻ bộ nhớ dựa vào tiến trình
Yêu cầu đầu tiên của xử lý song song là khả năng tạo ra một số các tiến trình cần thiết cho bài toán và khả năng huỷ bỏ chúng khi phần việc xử lý song song kết thúc để giải phóng tài nguyên mà các tiến trình đã chiếm giữ và không cản trở hoạt động của những tiến trình khác
Để thêm N tiến trình, chúng ta viết:
id = create_process(N);
Lệnh này tạo thêm N tiến trình và một tiến trình cha nữa để thực hiện câu lệnh đó, kết quả là có N+1 tiến trình như nhau được tạo ra và mỗi giá trị của id được gán tương ứng cho một tiến trình
Sử dụng những tiến trình đã được tạo ra chúng ta có thể viết chương trình song song dạng:
id = create_process(N);
Trang 33switch(id){
Lập trình chia sẻ bộ nhớ dựa vào luồng
Nhiều hệ điều hành hiện nay đều hỗ trợ đa luồng, ví dụ Window, OS/2, và UNIX Trong hệ thống SMP, những luồng khác nhau có thể được hệ điều hành lập lịch tự động cho những CPU khác nhau Một số ngôn ngữ lập trình, ví dụ Java cũng hỗ trợ lập trình
đa luồng
Một tiến trình là bức tranh về sự hoạt động của một chương trình Mỗi tiến trình được kết hợp với một hoặc nhiều luồng Các luồng có thể xem như các tập con của một tiến trình
Các luồng của một tiến trình có thể chia sẻ với nhau về không gian địa chỉ chương trình, các đoạn dữ liệu và môi trường xử lý, đồng thời cũng có vùng dữ liệu riêng để thao tác
Trang 34Các tiến trình và các luồng trong hệ thống song song cần phải được đồng bộ, song việc đồng bộ các luồng được thực hiện hiệu quả hơn đổi với các tiến trình Đồng bộ các tiến trình đòi hỏi tốn thời gian hoạt động của hệ thống, trong khi đối với các luồng thì việc
đồng bộ chủ yếu tập trung vào sự truy cập các biến chung của chương trình
Xử lý luồng trong Java
Java là ngôn ngữ lập trình hướng đối tượng hỗ trợ đa luồng Trong mô hình hướng đối
tượng, tiến trình và thủ tục là thứ yếu, mọi chức năng của chương trình được xác định thông qua các đối tượng Khái niệm luồng trong Java giống như trong các hệ điều hành được tích hợp vào ngôn ngữ
Cũng giống như trên, các luồng được tạo lập, sau đó thực hiện một số công việc và kết thúc hoạt động khi không còn vai trò sử dụng
Một luồng có thể ở một trong các trạng thái sau:
i new: khi một luồng mới được tạo ra với toán tử new()
ii runnable: khi chúng ta gọi phương thức start() để bắt đầu của một luồng iii blocked: từ trạng thái runnable chuyển sang trạng thái “bị chặn” khi gọi một trong các phương thức: sleep(), suspend(), wait(), hay bị chặn lại ở Input/output
iv dead: luồng chuyển sang trạng thái “chết” khi nó kết thúc hoạt động bình thường, hoặc gặp phải ngoại lệ không thực hiện tiếp được
Hình 1.20 mô tả sơ đồ chuyển trạng của các luồng trong hệ thống
wait chặn lại bởi I/O
Kết thúc I/O
suspend
Trang 35
Hình 1.20: Sơ đồ trạng thái của Thread
1.2.2.2.Tính toán phân tán, mô hình truyền thông điệp
Tính toán phân tán: Tính toán phân tán là những tính toán được thực hiện trên cơ sở kết hợp tính toán và truyền thông của hai hay nhiều máy tính trên mạng
Mô hình tính toán phân tán có những ưu điểm:
i Cho phép chia sẻ dữ liệu được lưu ở nhiều máy tính khác nhau
ii Chia sẻ với nhau về một số chức năng chính của máy tính
iii Độ tin cậy và khả năng dung thứ lỗi cao hơn Trong trường hợp có một máy tính bị trục trặc thì những máy tính khác có thể thay thế để hoàn thành nhiệm
Xử lý trong các hệ thống phân tán không có bộ nhớ chia sẻ để trao đổi dữ liệu với nhau
Sự trao đổi được thực hiện bằng cách truyền thông điệp Mô hình ở mức cao hơn, mô hình Client-Server cũng có thể sử dụng cơ chế này để cài đặt
Mô hình truyền thông điệp
Giống như mô hình chia sẻ bộ nhớ, các đơn vị xử lý song song trong mô hình truyền
thông điệp là các tiến trình Tuy nhiên cũng có một số điểm khác nhau giữa hai mô hình
này Trong mô hình truyền thông điệp:
Trang 36i Các tiến trình có thể thực hiện trên những bộ xử lý khác nhau và không truy cập được vào không gian địa chỉ chia sẻ Vì lý do này, những chương trình trao đổi thông điệp với nhau còn được gọi là các chương trình phân tán
ii Chỉ có kênh truyền là có thể chia sẻ cho các tiến trình, thường đó là LAN hoặc mạng diện rộng
iii Việc truyền thông và đồng bộ hoá hoạt động của các tiến trình được thực hiện
thông qua hai phương thức send() và receive()
iv Tất cả các biến là cục bộ của các tiến trình Vì thế, những vấn đề về xung đột
dữ liệu( cần phải khoá dữ liệu khi một tiến trình truy cập ), hay tranh chấp thông tin(bài toán loại trừ nhau) không xuất hiện trong mô hình tính toán phân tán
Việc đồng bộ hoá các tiến trình của một chương trình song song được thực hiện theo cơ
chế truyền thông điệp Khi một tiến trình muốn gửi một thông điệp thì nó phải chờ cho đến khi tiến trình nhận sẵn sàng nhận thông điệp đó và ngược lại, cũng tương tự
RMI và kỹ thuật lập trình phân tán đối tượng trong Java
Thông thường một chương trình được viết trong đó các mã lệnh, phương thức hay hàm,
dữ liệu được cài đặt cùng một máy cục bộ, vậy có cách nào nạp nội dung của hàm hay thủ tục ở một máy và gọi chúng ở máy khác? Đây chính là nội dung của lập trình phân tán mã lệnh RMI( Remte Method Invoke(triệu gọi phương thức từ xa)) Là cách thức giao tiếp giữa các đối tượng trong Java có các mã lệnh được cài đặt trên các máy tính khác nhau có thể triệu gọi lẫn nhau
Hình 1.21 minh hoạ cho việc triệu gọi phân tán Trên máy A, các phương thức A1, A2, A3 triệu gọi lẫn nhau được gọi là triệu gọi phương thức cục bộ( local method invoke ), A1 gọi đối tượng B1, C1, ; C1 gọi đối tượng B1 gọi là triệu gọi phương thức từ xa RMI
Trang 37Hình 1.21: Mô hình triệu gọi các đối tượng từ xa
Đối tượng java trên hai máy khác nhau không gọi nhau trực tiếp mà thông qua hai lớp trung gian Lớp trung gian này tồn tại ở cả máy chủ và máy khách Phía máy khách lớp trung gian này được gọi là Stub( lớp móc ), phía máy chủ lớp trung gian được gọi là Skeletion( lớp nối ), bạn hình dung Stub, Skeletion có vai trò như là trung gian môi giới
Trang 38Hình 1.22:Gọi phương thức của đối tượng thông qua lớp trung gian
Ví dụ: Trên hình 1.22 bạn có đôi tượng B1 được cài đặt trên máy B, trình biên dich Java giúp bạn tạo ra hai lớp trung gian B1_Stub và B1_Skel, B1_Stup sẽ được đem về máy A Khi A1 trên máy A gọi gọi B1, nó sẽ chuyển lời gọi đến B1_Stub, B1_Stub chịu trách nhiệm đóng gói tham số, chuyển tham số qua mạng đến máy B, trên máy B, lớp B1_Skel sẽ nhận tham số chuyển vào vùng không gian địa chỉ tương thích với đối tương B1, sau đó gọi phương thức tương ứng, kết quả nếu có do phương thức B1 trả về
sẽ được lớp B1_Skel đóng gói trả ngược về cho B1_Stub, B1_Stub chuyển giao kết quả cuối cùng về cho A1 Nhờ sự hổ trợ của lớp trung gian B1_Stub, khi kết nối mạng
bị sự cố lớp trung gian Stub luôn biết cách thông báo lỗi đến đối tượng A1
1.2.2.3 Lập trình trên cụm máy tính
Trang 39Mô hình truyền thông điệp nêu trên được sử dụng rất hiệu quả để lập trình song song theo cụm máy tính Một môi trường cho hệ thống nhiều máy tính, nhất là các cụm máy tính đã được phát triển và được sử dụng phổ biến hiện nay là PVM(Oak Ridge National Laboratories) PVM cung cấp môi trường phần mềm để truyền thông điệp cho các hệ máy tính thuần nhất và cả không thuần nhất PVM có một tập hợp các hàm thư viện được viết bằng C hoặc Fortran
Mỗi chương trình được viết bằng C, được biên dịch để chạy trên những kiểu máy tính xác định trên mạng Nếu mạng gồm những máy tính cùng kiểu thì chương trình chỉ cần dịch một lần Mỗi nút trong mạng( LAN ) phải truy cập đến hệ thống tệp chứa các chương trình đã được dịch để thực hiện
Tập các máy tính được sử dụng trong mạng phải được định nghĩa theo các mức ưu tiên
để chạy các chương trình Điều này được thực hiện trên tập máy ảo song song PVM
Cách thực hiện tốt nhất là tạo ra một danh sách tên gọi của các máy tính và đặt ở
hostfile Tệp này được PVM đọc để thực hiện các chương trình Mỗi máy tính có thể
chạy một hay nhiều tiến trình( chương trình ứng dụng ) Các chương trình ứng dụng chạy trong các máy tính thông qua các tiến trình của PVM để trao đổi với nhau trên mạng như hình 1.23 Các tiến trình PVM yêu cầu đủ thông tin để chọn lựa đường truyền dữ liệu
Máy tính trạm Máy tính
trạm
Máy tính trạm
PVM Chương trình ứng dụng
Trang 40Hình 1.23: Sự trao đổi thông điệp của các máy tính trong hệ PVM
1.2.2.4 Đánh giá các chương trình song song và phân tán
Để sử dụng hiệu quả các thuật toán song song, chúng ta cần phải biết cách đánh giá được chúng
Thời gian thực hiện song song
Để đánh giá được độ phức tạp tính toán của các thuật toán song song và phân tán, ngoài
số bước tính toán chúng ta còn phải quan tâm đến thời gian truyền thông điệp
Thời gian thực hiện song song, ký hiệu là t p gồm hai phần t comp và t comm
tp = tcomp + tcommTrong đó, tcomp là thời gian tính toán và tcomm là thời gian truyền thông dữ liệu
Thời gian tính toán tcomp được xác định giống như thuật toán tuần tự Khi có nhiều tiến trình tiến trình thực hiện đồng thời thì chỉ cần tính thời gian thực hiện của tiến trình phức tạp nhất( thực hiện lâu nhất ) Trong phân tích độ phức tạp tính toán, chúng ta luôn giả thiết rằng, tất cả các bộ xử lý là giống nhau và thao tác cùng một tốc độ như nhau Đối với những cụm máy tính không thuần nhất thì điều này không đảm bảo do
vậy, việc đánh giá thời tính toán của những hệ như thế là rất phức tạp