Giải thuật được chia làm ba đợt (giải thuật 5.3-1). Đợt đầu tiên xác định vòng rút gọn. Đợt tiếp theo là đợt bầu chọn tác tử thủ lĩnh. Để thu gọn vòng ứng viên, chúng ta cần xây dựng một cơ chế hợp tác giữa các tác tử, mỗi tác tử sẽ được cài đặt 5 thủ tục:
- Initiate: Khởi động giải thuật bầu chọn.
- INF: Tác tử ứng viên mang thông tin của nó di chuyển đến nút kế tiếp trên vòng rút gọn, và thực thi thủ tục INF trên nút này.
- REQ: Nút nhà u của ứng viên có định danh lớn hơn định danh của ứng viên có nút nhà v liền trước u, phát sinh bước di chuyển tới v mang thông báo REQ yêu cầu thông tin về ứng viên có nút nhà liền trước v. Tác tử mang thông báo REQ thực thi thủ tục REQ trên v.
- REP: Nút nhà v của ứng viên có định danh nhỏ hơn định danh của ứng viên có nút nhà u kế tiếp v, phát sinh bước di chuyển tới u mang thông báo REP chứa thông tin về ứng viên có nút nhà liền trước nút v. Tác tử mang thông báo REP này thực thi thủ tục REP trên u.
- Finish: Tác tử mang thông báo Finish quay trở về nút nhà, và thực thi thủ tục Finish tại nút nhà.
Đợt truyền bá thông tin, tác tử thủ lĩnh di chuyển trên vòng ảo rút gọn để thu thập và truyền bá thông tin cho tất cả các tác tử khác.
Khởi tạo:
Mỗi nút v khởi tạo thông tin trên bảng trắng: Nếu v là nút nhà của tác tử pi + ownerv = id(pi); Ngược lại + ownerv = NULL; + id(v): là định danh của nút v. + neigh_agentv = NULL; + cand_succv,= NULL; + cand_predv = NULL; + statusv = passive; + lockv = FALSE; Đợt xây dựng vòng rút gọn:
+ Tác tử pi di chuyển sang nút u tiếp theo trên vòng ảo cho đến khi owneru
NULL
- Tác tử pi thiết lập msg_agenti = id(u) và quay trở về nút nhà và cập nhật lại biến neigh_agentv = id(u), msg_agenti = NULL.
+ Khi tại mỗi nút nhà v của mỗi tác tử ta đều có neigh_agentv NULL, đợt xây dựng vòng rút gọn kết thúc.
Đợt bầu chọn thủ lĩnh:
Ban đầu tất cả các nút nhà v của mỗi tác tử ở trạng thái statusv = passive, lockv = FALSE.
Thủ tục khởi tạo Initiate
Tác tử pi trên v khởi động tự phát giải thuật bầu chọn: + Tác tử pi kiểm tra statusu:
ifstatusu = passive then
locku = TRUE;
msg_agenti = INF(ownerv, id(v));
home_nodei = id(v);
status_agenti = NULL;
cand_succv = NULL;
cand_predv = NULL;
lockv = FALSE;
Tác tử di chuyển đến nút u kế tiếp v trên vòng ảo rút gọn.
end if
Thủ tục nhận thông báo INF
Khi pi có msg_agenti = INF(ownerv, id(v)) di chuyển đến u:
- Tác tử pi đợi cho đến khi locku = FALSE: + locku = TRUE;
+ Tác tử pi kiểm tra statusu:
ifstatusu = passive then
statusu = dummy ; locku = FALSE;
Tác tử pi di chuyển sang nút hàng xóm neigh_agentu ;
else ifstatusu = candidatethen
cand_predu = (ownerv, id(v));
ifowneru > ownerv then
ifcand_succu = NULL then
statusu = waiting;
msg_agenti = REQ(owneru,id(u));
locku = FALSE;
Tác tử pi di chuyển đến nút v;
else /* cand_succu = (ownerk, id(k)) */
statusu = dummy;
msg_agenti = REP(cand_predu);
locku = FALSE;
Tác tử pi di chuyển đến nút k;
end if end if
ifowneru < ownerv then
ifcand_succu NULL then
/* cand_succu = (ownerk, id(k)) */
statusu = dummy;
msg_agenti = REP(cand_predu);
locku = FALSE;
else msg_agenti = FINISH; locku = FALSE; Tác tử pi di chuyển về nút nhà home_nodei; end if end if
ifowneru = ownerv then
statusu = leader; msg_agenti = FINISH; locku = FALSE; Tác tử pi di chuyển về nút nhà home_nodei; end if else msg_agenti = FINISH; locku = FALSE; Tác tử pi di chuyển về nút nhà home_nodei; end if
Thủ tục nhận thông báo REQ
Khi pi có msg_agenti = REQ(ownerv, id(v)) di chuyển đến u:
- Tác tử pi đợi cho đến khi locku = FALSE: + locku = TRUE;
+ Tác tử pi kiểm tra statusu:
ifstatusu = candidatethen
ifcand_predu = NULL then
cand_succu = (ownerv, id(v)); msg_agenti = FINISH; locku = FALSE; Tác tử pi di chuyển về nút nhà home_nodei; else statusu = dummy;
msg_agenti = REP(cand_predu);
locku = FALSE;
Tác tử pi di chuyển đến nút v;
end if
else ifstatusu = waitingthen
msg_agenti = FINISH; locku = FALSE; Tác tử pi di chuyển về nút nhà home_nodei; else msg_agenti = FINISH; locku = FALSE; Tác tử pi di chuyển về nút nhà home_nodei; end if
Thủ tục nhận thông báo REP
Khi pi có msg_agenti = REP (ownerv, id(v)) di chuyển đến u: - Tác tử pi đợi cho đến khi locku = FALSE:
+ locku = TRUE;
+ Tác tử pi kiểm tra statusu:
ifstatusu = waitingthen ifowneru = ownerv then
statusu = leader; msg_agenti = FINISH; locku = FALSE; Tác tử pi di chuyển về nút nhà home_nodei; else cand_predu = (ownerv, id(v));
if cand_succu = NULL then
ifownerv < owneru then
statusu = waiting;
msg_agenti = REQ(owneru,id(u));
locku = FALSE; Tác tử pi di chuyển đến nút v; else msg_agenti = FINISH; locku = FALSE; Tác tử pi di chuyển về nút nhà home_nodei; end if else /* cand_succu = (ownerk, id(k)) */ statusu = dummy;
msg_agenti = REP(cand_predu);
Tác tử pi di chuyển đến nút k; end if end if else msg_agenti = FINISH; locku = FALSE; Tác tử pi di chuyển về nút nhà home_nodei; end if Thủ tục kết thúc Finish
Khi pi có msg_agenti = FINISH di chuyển về nút nhà v:
- Tác tử pi kiểm tra statusv cho đến khi (statusv = dummy OR statusv = leader)
msg_agenti = NULL;
ifstatusv = leaderthen
status_agenti = leader;
else
status_agenti = dummy;
end if
Đợt truyền bá thông tin:
Tác tử thủ lĩnh pi di chuyển dọc theo vòng ảo rút gọn để thu thập và truyền bá thông tin cho tất cả các tác tử khác.
Ban đầu, mỗi nút v khởi tạo thông tin trên bảng trắng, nếu v là nút nhà của một tác tử pi, nó khởi tạo ownerv =id(pi), statusv = passive, ngược lại, ownerv = NULL,
statusv = NULL. Biến id(v) bằng định danh của nút v, các biến neigh_agentv , cand_succv , cand_predv khởi tạo bằng NULL. Ban đầu tác tử chưa thao tác gì trên bảng trắng của nút nhà của nó nên lockv = FALSE.
Giải thuật bắt đầu đợt đầu tiên với việc xây dựng vòng ảo rút gọn. Mỗi tác tử trên tất cả các nút tiến hành di chuyển sang nút tiếp theo trên vòng ảo cho đến khi nó di chuyển đến nút u là nút nhà của một tác tử trong mạng, tức là owneru NULL. Khi tại mỗi nút nhà v của mỗi tác tử đều có neigh_agentv NULL, đợt xây dựng vòng ảo rút gọn kết thúc.
Tiếp theo, một số tác tử trong mạng khởi động tự phát đợt bầu chọn thủ lĩnh, tác tử pi kiểm tra trạng thái statusv trên bảng trắng nút nhà v của nó, nếu statusv = passive
thì pi thiết đặt lockv = TRUE để khóa bảng trắng trên nút nhà v, đảm bảo chỉ có mình nó thao tác trên bảng trắng của nút v, pi thiết lập msg_agenti = INF(ownerv, id(v)) để
thực hiện bước di chuyển thông báo sang nút hàng xóm trên vòng ảo rút gọn;
home_nodei = v lưu nút nhà của tác tử pi, statusv = candidate để thiết lập trạng thái ứng viên cho tác tử pi; cand_succv , cand_predv lần lượt là ứng viên có nút nhà kế tiếp và liền trước nút nhà v của tác tử pi. Sau khi đã thiết lập xong các giá trị trên bảng trắng và gán giá trị cho các biến trên pi, tác tử pi mở khóa bảng trắng trên v bằng cách thiết đặt lockv = FALSE, và thực hiện di chuyển đến nút u kế tiếp nút v trên vòng ảo rút gọn.
Khi một tác tử pi với msg_agenti = INF(ownerv, id(v)) di chuyển đến u, nó thực hiện thủ tục nhận thông báo INF. Tác tử pi sẽ đợi trên u cho đến khi bảng trắng trên u
không bị thao tác bởi một tác tử khác, tức là locku = FALSE. Khi locku = FALSE, pi
thiết lập locku = TRUE để khóa bảng trắng trên u, tác tử pi kiểm tra biến trạng thái
statusu. Nếu statusu = passive, pi thiết lập statusu = dummy, có nghĩa tác tử có nút nhà là u sẽ không bao giờ trở thành thủ lĩnh, pi thiết lập locku = FALSE để mở khóa bảng trắng trên u, và thực hiện bước di chuyển sang nút neigh_agentu kế tiếp u trên vòng ảo rút gọn. Nếu statusu = candidate, pi thiết lập cand_predu = (ownerv, id(v)), nghĩa là ứng viên có nút nhà liền trước nút u là ứng viên có nút nhà v. Xảy ra các trường hợp sau đây:
Nếu owneru > ownerv , ta kiểm tra ứng viên có nút nhà kế tiếp nút u biến
cand_succu. Nếu cand_succu = NULL, thiết lập trạng thái đợi statusu = waiting
tại nút u, thiết lập thông báo yêu cầu nút v, thông tin về ứng viên có nút nhà liền trước nút v: msg_agenti = REQ(owneru,id(u)), mở khóa locku = FALSE bảng trắng trên u, pi di chuyển đến v. Ngược lại nếu cand_succu = (ownerk, id(k)), thiết lập statusu = dummy, có nghĩa tác tử có nút nhà là u sẽ không bao giờ trở thành thủ lĩnh, thiết lập thông báo trả lời thông tin về ứng viên có nút nhà liền trước u: msg_agenti = REP(cand_predu), mở khóa locku = FALSE, tác tử pi di chuyển đến nút k.
Nếu owneru < ownerv, ta kiểm tra ứng viên có nút nhà kế tiếp nút u biến
cand_succu. Nếu cand_succu = (ownerk, id(k)), thiết lập statusu = dummy, có nghĩa tác tử có nút nhà là u sẽ không bao giờ trở thành thủ lĩnh, thiết lập thông báo trả lời thông tin về ứng viên có nút nhà liền trước u: msg_agenti =
REP(cand_predu), mở khóa locku = FALSE, tác tử pi di chuyển đến nút k. Ngược lại thiết lập msg_agenti = FINISH, mở khóa locku = FALSE, tác tử pi di chuyển về nút nhà home_nodei của nó.
Nếu owneru = ownerv , tác tử có nút nhà là u sẽ trở thành thủ lĩnh statusu =
leader, thiết lập msg_agenti = FINISH, mở khóa locku = FALSE, tác tử pi di chuyển về nút nhà home_nodei của nó.
Khi một tác tử pi với msg_agenti = REQ(ownerv, id(v)) di chuyển đến u, nó thực hiện thủ tục nhận thông báo REQ. Tác tử pi đợi trên u cho đến khi locku = FALSE. Khi
locku = FALSE, pi thiết lập locku = TRUE để khóa bảng trắng trên u, tác tử pi kiểm tra biến trạng thái statusu. Có ba trường hợp xảy ra:
(1) Nếu statusu = candidate, có hai khả năng:
Nếu u chưa biết tác tử ứng viên liền trước nó cand_predu = NULL, pi thiết lập tác tử ứng viên kế tiếp là cand_succu (ownerv, id(v)), thiết lập
msg_agenti = FINISH, mở khóa locku = FALSE, tác tử pi di chuyển về nút
nhà home_nodei của nó.
Ngược lại, thiết lập thông báo trả lời v về ứng viên có nút nhà liền trước
u: msg_agenti = REP(cand_predu), mở khóa locku = FALSE, tác tử pi di chuyển đến nút v.
(2) Nếu statusu = waiting
Tác tử pi thiết lập tác tử ứng viên kế tiếp nó là cand_succu (ownerv, id(v)), thiết lập msg_agenti = FINISH, mở khóa locku = FALSE, tác tử pi
di chuyển về nút nhà home_nodei của nó. (3) Nếu statusu candidate và statusuwaiting
Tác tử pi thiết lập msg_agenti = FINISH, mở khóa locku = FALSE, tác tử
pi di chuyển về nút nhà home_nodei của nó.
Khi tác tử pi có msg_agenti = REP (ownerv, id(v)) di chuyển đến u, nó thực hiện thủ tục nhận thông báo trả lời REP. Tác tử pi đợi trên u cho đến khi locku = FALSE. Khi locku = FALSE, pi thiết lập locku = TRUE để khóa bảng trắng trên u, tác tử pi kiểm tra biến trạng thái statusu.
Nếu nút u đang ở trạng thái đợi statusu = waiting, có hai trường hợp xảy ra: (1) Nếu owneru = ownerv , tác tử có nút nhà là u sẽ trở thành thủ lĩnh statusu =
leader, thiết lập msg_agenti = FINISH, mở khóa locku = FALSE, tác tử pi di chuyển về nút nhà home_nodei của nó.
(2) Ngược lại owneru ownerv , pi thiết lập cand_predu = (ownerv, id(v)), nghĩa là ứng viên liền trước u là v. Có hai khả năng xảy ra:
o Nếu cand_succu = NULL, nghĩa là u chưa biết tác tử ứng viên có
nút nhà kế tiếp u trên vòng ảo rút gọn. Nếu ownerv < owneru , thiết lập trạng thái đợi statusu = waiting tại nút u, thiết lập thông báo yêu cầu v, thông tin về ứng viên có nút nhà liền trước v, bằng thông báo
msg_agenti = REQ(owneru,id(u)), mở khóa locku = FALSE bảng trắng trên u, pi dư cư đến v. Ngược lại ownerv > owneru , tác tử pi
thiết lập msg_agenti = FINISH, mở khóa locku = FALSE, tác tử pi
di chuyển về nút nhà home_nodei của nó.
o Nếu cand_succu = (ownerk, id(k)), thiết lập statusu = dummy, có nghĩa tác tử có nút nhà là u sẽ không bao giờ trở thành thủ lĩnh,
thiết lập thông báo trả lời thông tin về ứng viên có nút nhà liền trước u: msg_agenti = REP(cand_predu), mở khóa locku = FALSE, tác tử pi di chuyển đến nút k
Nếu nút u không ở trạng thái đợi statusu waiting. Tác tử pi thiết lập
msg_agenti = FINISH, mở khóa locku = FALSE, tác tử pi di chuyển về nút nhà
home_nodei của nó.
Khi pi có msg_agenti = FINISH di chuyển về nút nhà v, nó thực hiện thủ tục kết thúc. Tác tử pi kiểm tra statusv cho đến khi statusv = dummy hoặc statusv = leader. Khi
statusv = dummy hoặc statusv = leader, tác tử pi thiết lập msg_agenti = NULL, tác tử pi
kết thúc đợt bầu chọn tại nút nhà v. Nếu tác tử pi kiểm tra thấy statusv = leader, pilà tác tử thủ lĩnh; ngược lại nếu statusv = dummy, tác tử pikhông được bầu chọn làm thủ lĩnh.
Đợt truyền bá thông tin, tác tử thủ lĩnh di chuyển dọc theo vòng ảo rút gọn, để thu thập và truyền bá thông tin cho các tác tử khác.
Ví dụ thực hiện:
Hình 5.3-1 minh họa thực hiện giải thuật cho một hệ tác tử di động đơn giản, bao gồm bảy nút và bốn tác tử, các nút và tác tử được bố trí như hình 5.3-1.a. Tất cả các nút được kết nối đầy đủ, mỗi tác tử ban đầu không biết các định danh của tất các tác tử và các nút khác, cũng không biết trước số nút N và số tác tử k. Giả thiết sự tồn tại một vòng ảo trong mạng kết nối các nút với nhau theo hướng ngược chiều kim đồng hồ, mỗi nút chỉ biết định danh của nút kế tiếp nó ở trên vòng.
Giải thuật bắt đầu bằng đợt xây dựng vào ảo rút gọn, các tác tử di chuyển đến nút tiếp theo trên vòng ảo cho đến khi nó gặp được một nút u là nút nhà của một tác tử trong mạng, tác tử ghi nhớ định danh của u và trở về nút nhà v của nó, tác tử thiết lập
Hình 5.3-1.a. Trạng thái ban đầu của mạng
2 1 2 3 4 6 1 7 3 4 5
biến neigh_agentv = id(u). Nút u chính là nút kế tiếp nút v trên vòng ảo rút gọn. Khi đợt này kết thúc, ta thu được vòng ảo rút gọn như hình 5.3-1.b.
Tác tử 1, 3 và 4 bắt đầu đợt bầu chọn thủ lĩnh bằng cách thực hiện thủ tục khởi tạo. Tác tử 1 thiết lập trạng thái nút nhà 1 là candidate mang theo thông báo INF(1,1) di chuyển sang nút 3. Tác tử 2 chưa bắt đầu đợt bầu chọn, trạng thái nút 3 vẫn là
passive, tác tử 1 thiết lập trạng thái nút 3 là dummy và di chuyển sang nút 5. Tác tử 3 thiết lập trạng thái nút nhà 5 là candidate mang theo thông báo INF(3,5) và di chuyển sang nút số 7. Tác tử 4 thiết lập trạng thái nút nhà 7 là candidate mang theo thông báo
INF(4,7) di chuyển sang nút 1. Hình 5.3-1.c minh họa thủ tục khởi tạo đợt bầu chọn.
Tác tử 4 mang thông báo INF(4,7) di chuyển đến nút 1, vì status1 = candidate,