Heuristic đƣợc đƣa ra ở trên dẫn đến một thuật toán đơn giản nhƣng hiệu quả để phát hiện các nút gần biên, nhƣ đƣợc mô tả trong Bảng 3.1. Mỗi nút p khám phá tất cả các
láng giềng của nó, tạo danh sách các láng giềng (MYNB) rồi gửi danh sách các láng giềng đến tất cả các nút cách nó hai chặng. Nếu nhận đƣợc danh sách láng giềng từ các nút cách p hai chặng, p tạo 2NG của nó, gọi là G2, dựa trên các danh sách các láng giềng đã nhận đƣợc. Tiếp theo, p kiểm tra G2 có tạo thành một cái vành hay không bằng cách gọi hàm IsRing(G2). Nếu G2 là một cái vành, nghĩa là IsRing(G2) trả về true, thì đặt nearBoundaries = false (p không gần biên), ngƣợc lại đặt nearBoundaries = true (p gần
biên).
Bảng 3.1. Thuật toán phát hiện biên đƣợc đề xuất, mã cho nút p.
---
Vào: Không.
Ra: nearBoundaries = true nếu p gần biên, nearBoundaries = false nếu p không gần biên.
Khởi tạo:
nearBoundaries ← false
MYNB ← {tất cả các láng giềng của p}
V ← {}
48
broadcast(p.id, MYNB, 1)
onReceive(id, NB, hop):
if hop = 1 then broadcast(id, nb, 2)
else if id∉V and id∉MYNB and id ≠ p.id then
V ← V ∪ {id} foreach v∈NB PE ← PE∪ {<id, v>} E ← {} foreach <v1, v2> ∈PE if v1 ∈V and v2 ∈V then E ← E∪ {<v1, v2>} G2 ← <V, E>
if IsRing(G2) then nearBoundaries ← false
else nearBoundaries ← true
IsRing(G2 ≡<V2, E2>):
if not IsConnected(G2) then return false
else t ← anyElementOf(V2) V20 ← {t} V21 ← {v∈V2 | <v, t> ∈E2} V22 ← {v∈V2 | v ≠ t and v∉V21 and ∃𝑢∈V21: <u, v> ∈E2} E22 ← {<u, v> ∈E2 | u∈V22 and v∈V22} g2 ← <V22, E22>
if V22 = {} or IsConnected(g2) then return false
else
V‟2 ← V2 – V20 – V21
E‟2 ← {<u, v> ∈E2 | u∈V‟2 and v∈V‟2}
G‟2 ← <V‟2, E‟2>
if not IsConnected(G’2) then return false
49 IsConnected(G ≡ <V, E>): k ← anyElementOf(V) L ← [k] V ← V – {k} while L ≠ [] l ← L[0] L ← L[1:] foreach m∈V if <l, m> ∈E then V ← V – {m} L ← L + [m] if V ≠ {} then return false
else return true
---
Trong thuật toán đƣợc đề xuất, đồ thị vùng lân cận 2 chặng G2 đƣợc lƣu trữ và
IsRing(G2) đƣợc thực thi cục bộ tại mỗi nút. Sau hai vòng không đồng bộ, mỗi nút P biết
topo của vùng lân cận bao gồm các nút cách xa P không quá hai chặng. G2 đƣợc trích ra từ topo này. Hàm IsRing(G2) đƣợc gọi để kiểm tra xem G2 có là một cái “vành” hay
không. Để kiểm tra xem đồ thị vùng lân cận 2 chặng G2 có tạo thành một cái vành hay không, đầu tiên tính liên thông của nó đƣợc kiểm tra bằng việc áp dụng thuật toán loang màu (gọi hàm IsConnected(G2)): chọn một nút bất kỳ k thuộc G2, tô màu cho k và tất cả các nút thuộc G2 liên thông với k. Nếu sau khi áp dụng thuật toán loang màu vẫn còn nút thuộc G2 không đƣợc tô thì G2 không liên thông; ngƣợc lại G2 liên thông. Rõ ràng rằng
G2 không thể là một cái vành nếu nó không liên thông. Trong trƣờng hợp G2 liên thông, G2 có thể là một cái vành hoặc chỉ là một mảnh vỡ của cái vành. Để biết G2 là cái vành
hay chỉ là một mảnh vỡ, chúng ta cắt loại bỏ một phần của G2 bao gồm nút bất kỳ t, các láng giềng của nó (V21) và các láng giềng của láng giềng của nó (V22), rồi kiểm tra các mảnh còn lại. Nếu chúng ta không thể cắt một phần đủ lớn (g2 liên thông hoặc không có nút nào), thì G2 đích thực không phải là một cái vành. Ngƣợc lại, nếu chúng ta còn hai
50
mảnh (G’2 không liên thông), thì G2 cũng không phải là một cái vành. G2 là một cái
vành chỉ khi chúng ta có duy nhất một mảnh còn lại vừa khớp với mảnh bị cắt và loại bỏ. Trực quan của việc cắt loại bỏ một mảnh và kiểm tra các mảnh còn lại của G2 đƣợc minh họa trong Hình 3.3.
(a) (b) (c) (d)
Hình 3.3. Minh họa thuật toán kiểm tra khả năng gần biên. Một cái vành hoặc một mảnh vỡ của cái vành sau khi đƣợc cắt và loại bỏ một phần. Phần đƣợc cắt và loại bỏ có màu tím. Các mảnh còn lại có màu xanh. (a) Một mảnh còn lại vừa với mảnh bị cắt và loại bỏ. (b) Hai mảnh còn lại.
(c), (d) Không thể cắt và loại bỏ mảnh đủ lớn.