Xây dựng thuật toán tuần tự tìm đường đi ngắn nhất trên đồ thị

Một phần của tài liệu NGHIÊN CỨU THUẬT TOÁN SONG SONG 10600811 (Trang 34)

7. Cấu trúc báo cáo

3.1.2.Xây dựng thuật toán tuần tự tìm đường đi ngắn nhất trên đồ thị

3.1. THUẬT TOÁN DIJKSTRA

3.1.2.Xây dựng thuật toán tuần tự tìm đường đi ngắn nhất trên đồ thị

Thuật toán được xây dựng trên cơ sở gán cho các đỉnh các nhãn tạm thời. Nhãn của mỗi đỉnh cho biết cận trên của độ dài đường đi ngắn nhất từ đỉnh nguồn đến nó. Các nhãn này sẽ được biến đổi theo một thủ tục lặp, mà ở mỗi bước lặp, có một nhãn tạm thời trở thành nhãn cố định. Nếu nhãn của một đỉnh nào đó trở thành cố định thì nó sẽ cho ta khơng phải là cận trên mà

là độ dài đường đi ngắn nhất từ đỉnh nguồn đến nó. Thuật tốn tìm đường đi ngắn nhất tứ đỉnh i đến đỉnh j: Gọi L là ma trận kề chứa trọng số giữa các cặp đỉnh, quy ước, Lhk = ∞ nếu khơng có cạnh nối từ đỉnh h đến đỉnh k.

Gọi Length[] là mảng chứa nhãn của đỉnh.

Gọi Last[] là mảng

đường đi.

Bước 1: gán T = V và gán nhãn:

Length[i] = 0

Length[k] = ∞ với k V \ {i} Last[k] = -1 với k V

Bước 2: Chọn đỉnh v T sao cho Length[v] nhỏ nhất và gán T = T\ {v}.

Bước 3: Nếu v = j thì dừng và giá trị Length[j] là độ dài đường đi ngắn nhất từ i đến j

và Last[j] lưu đỉnh nằm ngay trước j trên đường đi đó. Nếu Length[j] = ∞ thì khơng tồn tại đường đi. Kết thúc.

Nếu Length[v] = ∞ thì khơng tồn tại đường đi. Kết thúc.

Bước 4: Duyệt, k T và Lvk 0:

Nếu Length[k] > Length[v] + Lvk thì Length[k] = Length[v] + Lvk Last[k] = v;

Kết thúc nếu Kết thúc duyệt Trở về bước 2.

3.1.3. Song song hố thuật tốn tìm đường đi ngắn nhất trên đồ thị

Lúc này, việc thực thì thuật tốn khơng chỉ trên một BXL mà phân phối công việc cho các bộ xử lý, mỗi BXL sẽ đảm nhận 1 số đỉnh của đồ thị thông qua ma trận mô tả quan hệ của các đỉnh đó với các đỉnh cịn lại. Ta sẽ song song hoá thuật toán Dijkstra tuần tự tại bước 3 và bước 4.

Thuật toán

Giả sử ta có m BXL P, n là số đỉnh của đồ thị, thì mỗi BXL sẽ quản lý n/m số đỉnh, nếu n/m dư, thì P0, P1,…Pm-2 sẽ quản lý n/m đỉnh, và Pm-1 sẽ quản lý các đỉnh còn lại.

Mỗi Pi sẽ lưu lại một ma trận LPi với số cột là số đỉnh do Pi quản lý, và số hàng là số đỉnh của đồ thị (hình 16).

Bước 1: Khởi tạo tập đỉnh T = V, Length[k] = ∞ với k, Length[i] = 0.

Phân chia dữ liệu trong ma trận trọng số L đến các bộ xử lý. Với mỗi bộ xử lý ta có một ma trận con tương đương với một ma trận con của L nhận dữ liệu. Mỗi Pi khác P0 sẽ lưu một mảng đỉnh riêng Vi cho riêng mình.

Bước 2: Từ BXL chính P0, gửi đỉnh i và Length[i] đến các BXL còn lại Bước 3:Gọi đỉnh được truyền đi là s, và nhãn của đỉnh đó là w.

Mỗi Pi sẽ cập nhật mảng Length[] với Length[k] = Min(Length[k], w + LP[s][k]) với mọi k thuộc về Vi.

Mỗi Pi sẽ tính tốn Min Li và gửi về đỉnh và nhãn nhỏ nhất cho BXL chính.

Bước 4: BXL chính sẽ chọn đỉnh có Min Length nhỏ nhất và nhãn của nó, gán cho s,

và w. loại s ra khỏi T. Nếu s là đỉnh đích hoặc w = ∞ thì ngừng truyền, kết thúc. Nếu w tồn tại thì w là độ dài đường đi ngắn nhất.

Lặp lại bước 3.

Hình 18. Thuật tốn Dijkstra song song – Client

3.1.4. Kết quả nghiên cứu

Qua quá trình nghiên cứu và thử nghiệm, tôi đã cài đạt thành cơng thuật tốn song song hố thuật tốn Dijkstra tuần tự. Chương trình tương ứng cài đặt bằng Java (hình 11, hình 12), cơ sở dữ liệu MySql cho kết quả chính xác. (adsbygoogle = window.adsbygoogle || []).push({});

Thuật tốn đã được thử nghiệm trên máy Acer 4920 chíp lõi kép 2,2GHz, mỗi kết quả được tính trung bình sau 5 lần chạy ngẫu nhiên (bảng 3). Mặc dù nắm vững lý thuyết, nhưng thời gian dùng cho việc truyền thơng chiếm dụng nhiều gây lãng phí cho thời gian thực hiện chương trình. Do đó kết quả khi thực hiện có phần khơng tốt.

Cơ sở dữ liệu

Table Field Type

Edqes Node1 char(5) Node2 char(5) Time int(5) Name char(50) One-Way tinyint(1) Nodes No char(5) Name char(50) Path_Input No char(5) Name char(50) Start char(5) End char(5) Path_Output No char(5) Length int(9) Path varchar(200)

Chương trình tự động thiết kế 4 cơ sở dữ liệu để thử nghiệm với tỉ lệ cạnh ~0.82 :

Database Nodes Edqes Tow-Way One-Way

Net1 800 532851 213251 106349

Net2 500 207848 83098 41652

Net3 300 74792 29942 14908

Net4 100 8198 3239 1711

Bảng 2. Cấu trúc Cơ Sở Dữ Liệu – Dijkstra

Giao diện

- Thiết kế giao diện cho Demo tuần tự

Hình 19. Giao diện Demo Dijkstra tuần tự

- Thiết kế giao diện cho Server

- Thiết kế giao diện cho Client

Hình 21. Giao diện Demo Dijkstra song song – Client

Đỉnh Cạnh Tuần

Tự(s)

Song Song(s)

2 Client 5 Client 10 Client

800 532729 30.3 36.5 32.5 24.6

500 207848 13.2 27 22.4 10.4

300 74792 6.4 7.6 7.4 16.6

100 8189 1.2 1.4 2.4 4.6

Đồ thị 1. So sánh kết quả tương đối – Dijkstra

Đồ thị cho ta một sô nhận xét sau:

- Thời gian tính tốn tuần tự tăng khi số đỉnh đồ thị tăng

- Tính tốn song song hồn tồn khả thi ở đồ thị có số lượng đỉnh lớn

- Cần xem xét số BXL tính tốn trên một đồ thị nhất định để cho kết quả tối ưu Mặc dù thời gian có hạn, bên cạnh đó đề tài gặp phải một số khó khăn trong việc tìm hiểu và cài đặt do đây là một đề tài khá mới, ít được quan tâm nhưng đề tài cũng cố gắng để đạt được các mục tiêu đã đề ra. (adsbygoogle = window.adsbygoogle || []).push({});

Chương trình tương ứng có thể kết nối nhiều Client, và mỗi Client có thể xử lý tuỳ biến và thực hiện đúng kết quả cần thiết.

3.2. THUẬT TỐN PRIM

3.2.1. Phát biểu bài tốn

Cho đồ thị vô hướng G(V, E) liên thông với tập V đỉnh và E cạnh. Mỗi cạnh e của đồ thị có trọng số c(e), gọi là độ dài của nó. Giả sử H = (V, T) là 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ủa các cạnh của nó:

Bài tốn được đặt ra là trong số tất cả các cây khung của đồ thị G hãy tìm cây khung với độ dài nhỏ nhất. Một thể hiện của bài toán trong thực tế là bài tốn thiết lập mạng truyền thơng, ở đó các đỉnh là các thành phố và các cạnh của cây bao trùm là đường nối mạng giữa thành phố.

3.2.2. Xây dựng thuật tốn tuần tự tìm cây khung nhỏ nhất

Trong phương pháp này, bắt đầu từ một đỉnh s tuỳ ý của đồ thị, đầu tiên nối s với đỉnh lân cận gần nó nhất, chẳng hạn là đỉnh y. Nghĩa là trong tất cả các cạnh kề của s thì cạnh (s,y) nhỏ nhất. Tiếp theo, trong số các cạnh kề với 2 đỉnh s và y ta tìm cạnh có độ dài nhỏ nhất, cạnh này dẫn đến đỉnh thứ 3 z, quá trình này sẽ được tiếp tục cho đến khi ta thi được cây gồm n đỉnh và n – 1 cạnh sẽ chính là cây khung nhỏ nhất cần tìm

Thuật tốn tìm cây khung nhỏ nhất:

Gọi L là ma trận kề chứa trọng số giữa các cặp đỉnh, quy ước, Lhk = ∞ nếu khơng có cạnh nối từ đỉnh h đến đỉnh k.

Gọi H ma trận kề của cây khung nhỏ nhất của đồ thị G.

Gọi mảng near[i] là mảng lưu đỉnh mà cạnh nối giữa đỉnh đó và đỉnh i có độ dài nhỏ nhất trọng số các cạnh nối với i

Gọi mảng length[i] lưu trọng số của cạnh (i, near[i]).

Bước 1: Gán T = V. H[p][q] =

false.

length[i] = 0; length[k] = với k V \ {i}; near[i] = i, near[k] = -1 với k V \ {i}.

Bước 2: Chọn đỉnh v T sao cho length[v] nhỏ nhất và gán T = T\{v}, H[v][near[v]]

= true.

Bước 3: Nếu T = null thì dừng, H là cây khung nhỏ nhất. Kết thúc. Bước 4: Duyệt: k T và Lvk 0: Nếu length[k] > Lvk thì length[k] = Lvk near[k] = v Kết thúc nếu Kết thúc duyệt Trở về bước 2.

3.2.3. Song song hố thuật tốn tìm cây khung nhỏ nhất

Do hai thuật toán Dijkstra và Prim gần giống nhau về mặt bản chất, đó là cùng tìm giá trị nhỏ nhất. đối với Prim đó là cạnh có trọng số nhỏ nhất, cịn đối với Dijkstra là đỉnh có độ dài từ đỉnh nguồn đến nó nhỏ nhất. Nên về mặt song song hố thuật toán Prim cũng tương tự như thuật toán Dijkstra.

Thuật toán

Giả sử ta có m BXL P, n là số đỉnh của đồ thị, thì mỗi BXL sẽ quản lý n/m số đỉnh, nếu n/m dư, thì P0, P1,…Pm-2 sẽ quản lý n/m đỉnh, và Pm-1 sẽ quản lý các đỉnh còn lại.

Mỗi Pi sẽ lưu lại một ma trận LPi với số cột là số đỉnh do Pi quản lý, và số hàng là số đỉnh của đồ thị.

Bước 1: Khởi tạo tập đỉnh T = V, Length[k] = ∞ với k, Length[i] = 0.

Phân chia dữ liệu trong ma trận trọng số L đến các bộ xử lý. Với mỗi bộ xử lý ta có một ma trận con tương đương với một ma trận con của L nhận dữ liệu. Mỗi Pi khác P0 sẽ lưu một mảng đỉnh riêng Vi cho riêng mình.

Bước 3: Gọi đỉnh được truyền đi là s.

Mỗi Pi sẽ cập nhật mảng Length[] với Length[k] = Min(Length[k], LP[s][k]) với mọi k thuộc về Vi.

Mỗi Pi sẽ tính tốn Min Li và gửi về đỉnh và nhãn nhỏ nhất cho BXL chính.

Bước 4: BXL chính sẽ chọn đỉnh có Length nhỏ nhất gán cho s, loại s ra khỏi T, gán

H[s][near[s]] = true. Nếu s là đỉnh cuối cùng thì ngừng truyền, H là cây khung nhỏ nhất. Kết thúc. Lặp lại bước 3. (adsbygoogle = window.adsbygoogle || []).push({});

3.2.4. Kết quả nghiên cứu

Cơ sở dữ liệu

Table Field Type

Edqes Node1 char(5) Node2 char(5) Time int(5) Name char(50) Nodes No char(5) Name char(50) Path_Input No char(5) Name char(50) Start char(5) End char(5) Path_Output No char(5) Length int(9) Path varchar(200)

Bảng 5. Cấu trúc Cơ Sở Dữ Liệu – Prim

Chương trình tự động thiết kế 4 cơ sở dữ liệu để thử nghiệm với tỉ lệ cạnh ~0.82.

Database Nodes Edqes

Netp4 800 543651

Netp3 500 218848

Netp2 300 75342

Netp1 100 8658

Giao diện

- Thiết kế giao diện cho Demo tuần tự

Hình 25. Giao diện Demo Prim tuần tự

- Thiết kế giao diện cho Server

- Thiết kế giao diện cho Client

Hình 27. Giao diện Demo Prim song song – Client

Đỉnh Cạnh Tuần

Tự(s)

Song Song(s)

2 Client 5 Client 10 Client

800 532729 60 55.5 50 47

500 207848 22 30 33 25

300 74792 7 15 18 15.5

100 8189 0 4 5.5 6

Kết quả thu được tương tự như kết quả thử nghiệm thuật toán Dijkstra song song.

Do điều kiện kỹ thuật không cho phép nên không thể thử nghiệm ở những đồ thị lớn hơn, vì vậy kết quả khi thực hiện có phần khơng tốt.

KẾT LUẬN

Tính tốn song song đang ngày càng có nhiều ứng dụng trong thực tế. Đặc biệt là khi có nhiều tài ngun máy tính dư thừa đang kết nối trên internet và nhiều máy tính để bàn có năng lực xử lý tính tốn lớn. Trong lĩnh vực công nghệ thông tin http://www1.dantri.com.vn/vieclam/2007/8/194136.vip đang dự báo một nghề mới đang hình thành, đó là nghề “lập trình song song”, vì vậy việc đầu tư nghiên cứu các kỹ thuật và phương pháp lập trình song song là nhu cầu cần thiết.

Áp dụng tính tốn song song ln ln cho phép tối ưu thời gian. Tuy nhiên chúng ta cần đầu tư nghiên cứu các thuật toán tuần tự để xây dựng được thuật tốn song song có hiệu quả. (adsbygoogle = window.adsbygoogle || []).push({});

Dựa trên kiến thức đã tìm hiểu được về tính tốn song song, cách thức phát triển trong mơi trường hổ trợ tính tốn song song, đề tài đã đạt được mục tiêu đề ra là nghiên cứu về tính tính tốn song song và thực nghiệm trên thuật toán Dijkstra và thuật toán Prim tuần tự.

Đề tài có tiềm năng ứng dụng rất lớn, tính tốn song song là phương pháp giải quyết bài toán thời gian tối ưu hiện nay. Đề tài sẽ tiếp tục cải tiến chương trình, tối ưu các thuật tốn, nhằm đạt được kết quả tối nhất. Bên cạnh đó, mở rộng ra nhiều thuật tốn khác trên đồ thị.

TÀI LIỆU THAM KHẢO Tài liệu tiếng Việt

[1] PGS. TSKH Trần Quốc Chiến, Giáo trình lý thuyết đồ thị và ứng dụng, Đại Học Đà Nẵng, 2007.

[2] Đoàn Văn Ban, Nguyễn Mậu Hân, Xử lý song song và phân tán, NXB

KH&KT, 2006.

[3] ThS. Lê Văn Mỹ, Giáo trình lập trình mạng, Đại Học Đà Nẵng,

[4] Vương Thông, Ứng dụng tính tốn song song trong nhận dạng mặt người, Luận văn thạc sỹ Đại Học Đà Nẵng, 2008, trang 1 – 45.

[5] Huỳnh Bá Thanh Tùng, Trần Việt Cường, Nghiên cứu tính tốn lưới và thử nghiệm một số thuật toán lý thuyết đồ thị, Luận văn cử nhân Đại Học KHTN Tp.HCM, 2005, trang 115 – 128.

Tài liệu tiếng Anh

[1] Java Network Programming Elliotte Rusty Harold

Tài liệu khác

[1] www.java2s.com

[2] www.cac.cornell.edu/VW/Parallel/tax.aspx

PHỤ LỤC

MỘT SỐ HÀM VÀ LỚP CHÍNH TRONG CHƯƠNG TRÌNH MƠ PHỎNG 6.1. Chương trình mơ phỏng thuật tốn Dijkstra tuần tự

Hàm/ Lớp Chức năng

Funclion init(Connect conn) Lấy dữ liệu từ database, khởi tạo giá trị ban đầu

Funclion Boolean Deplay(int a, int b) Trả về true nếu tìm thấy đường đi. Class Connect Tạo đối tượng kết nối cơ sở dữ liệu Class BackgroundConnect Điều khiển giao diện chính của

6.2. Chương trình mơ phỏng thuật tốn Dijkstra song song 6.2.1. Server 6.2.1. Server

Hàm/ Lớp Chức năng

Funclion boolean Process(String str) Chờ client kết nối, trả về true nếu đã đủ số client yêu cầu.

Funclion init(Connect conn) Lấy dữ liệu, phân rã, chuyển dữ liệu đến các client.

Function Deplay(int a, int b) Trả về true nếu tìm thấy đường đi. Class BackgroundServer Điều khiển giao diện chính của chương

trình.

Class Message Nhận và gửi thơng điệp

6.2.2. Client

Hàm/ Lớp Chức năng

Funclion ListenProcessSend() Kết nối, lắng nghe và trả lời yêu cầu từ server

Funclion int[] MinNode(String test) Lấy dữ liệu, phân rã, chuyển dữ liệu đến các client. (adsbygoogle = window.adsbygoogle || []).push({});

Function String UpdateMinFindTrue(int a, int w)

Trả về message gửi cho server

Class BackgroundClient Điều khiển giao diện chính của chương trình.

6.3. Chương trình mơ phỏng thuật tốn Prim tuần tự

Hàm/ Lớp Chức năng

Funclion init(Connect conn) Lấy dữ liệu từ database, khởi tạo giá trị ban đầu

Funclion Boolean Deplay(int a) Trả về true nếu tìm thấy cây khung nhỏ nhất

Class Connect Tạo đối tượng kết nối cơ sở dữ liệu Class BackgroundConnect Điều khiển giao diện chính của

6.4. Chương trình mơ phỏng thuật tốn Prim song song 6.4.1. Server

Hàm/ Lớp Chức năng

Funclion boolean Process(String str) Chờ client kết nối, trả về true nếu đã đủ số client yêu cầu.

Funclion init(Connect conn) Lấy dữ liệu, phân rã, chuyển dữ liệu đến các client.

Function Deplay(int a) Trả về true nếu tìm thấy cây khung nhỏ nhất.

Class BackgroundServer Điều khiển giao diện chính của chương trình.

Class Message Nhận và gửi thông điệp

6.4.2. Client

Hàm/ Lớp Chức năng

Funclion ListenProcessSend() Kết nối, lắng nghe và trả lời yêu cầu từ server

Funclion int[] MinNode(String test) Lấy dữ liệu, phân rã, chuyển dữ liệu đến các client.

Function String UpdateMinFindTrue(int a)

Trả về message gửi cho server Class BackgroundClient Điều khiển giao diện chính của

chương trình.

Một phần của tài liệu NGHIÊN CỨU THUẬT TOÁN SONG SONG 10600811 (Trang 34)