Mục này trình bày tóm tắt năm thuật tốn cận tỷ lệ tốt nhất hiện biết để tiến hành đánh giá thực nghiệm.
3.1.1.1 Thuật toán Blum et al.
Blum et al. [6] cho rằng chi phí tối ưu của bài toán k−MST (bài toán cây khung nhỏ nhất đi qua k đỉnh [15]) được xem như cận dưới của độ trễ đỉnh thứ k trong hành trình tối ưu MLP.
Thuật tốn Blum et al. được trình bày như sau: Giả sử, có tập lời giải Tk thu được từ thuật toán gần đúng cận tỷ lệ β cho bài toán k−MST với gốc v1 (k = 2, 3, …, n). Đối với mỗi số nguyên l (l = 2, 3, .., n), chọn cây Tl có chi phí lớn nhất trong khoảng (2l, 2l+1]. Sau đó, với mỗi cây Tl, nhân đôi mỗi cạnh của cây để thu được một chu trình Euler Cl (l = 2, 3, …, n) có gốc là v1. Kết nối các chu trình Cl, đồng thời loại bỏ các đỉnh đã được duyệt từ các chu trình
Thuật tốn có cận tỷ lệ là 16 nếu sử dụng thuật toán gần đúng cận tỷ lệ 2 cho bài toán
k−MST [15]. Giải bài tốn k−MST, chúng ta cần O(n(n+log cmax))×log n) để gọi PCST (Prize
collection steiner tree) với cmax là chi phí cạnh lớn nhất và O(n2×log n) để thực thi PCST. Bởi vậy, độ phức tạp thời gian của thuật tốn là O(n3(n+log cmax))×log2 n).
3.1.1.2 Thuật tốn Goeman et al.
Goemans et al. [18] cho rằng nếu có một thuật tốn tìm hành trình ngắn nhất đi qua k đỉnh
trong không gian metric với cận tỷ lệ β, thì tồn tại một thuật tốn có cận tỷ lệ 359×β cho bài tốn MLP. Với mỗi j = 1, 2, …, n, thuật tốn tìm hành trình ngắn nhất Tj đi qua j đỉnh. Sau đó, ta kết nối các Tj để thu được hành trình MLP. Mục đích của việc kết nối là lựa chọn các chỉ số j1, …, jm sao cho khi kết nối các
1 j T , ..., m j T ta thu được hành trình có độ trễ là nhỏ nhất. Để kết nối các hành trình Tj (j = 2, 3, …, n), Goemans et al. đưa ra thuật toán như sau: Xây dựng đồ thị đầy đủ có hướng Gn với cung (i, j) đi từ min (i, j) đến max (i, j) và có độ dài là ( ( ))
2
j n i j d
(với dj là độ dài của Tj). Thuật tốn sau đó tìm đường đi ngắn nhất từ đỉnh 1 đến đỉnh n. Giả sử, đường đi đó đi qua các đỉnh 1 = j1 < j2 < ... < jm = n, thì hành trình MLP cuối cùng thu được bằng việc kết nối T =
1 j T , ..., . m j T
Sử dụng thuật toán cận tỷ lệ β = 2 cho bài tốn k–MST [15], ta thu được một thuật
tốn có cận tỷ lệ là 7.18 cho bài toán MLP. So với thuật tốn của Blum et al., thì thuật tốn Goeman et al. cho cận tỷ lệ tốt hơn. Tuy nhiên, vẫn cần O(n(n+logcmax)×log n) để gọi PCST để tạo ra các k–MST, bởi vậy, thuật tốn khơng cải thiện được về thời gian chạy.
3.1.1.3 Thuật toán Archer et al.
Archer et al. [1] khơng sử dụng thuật tốn k-MST trong [15], thay vì đó, Archer et al. đề xuất thuật toán tạo ra một tập các cây k–MST (k = 2, …, n) bằng việc sử dụng kỹ thuật nới lỏng lagrangian. Sau đó, các cây này được kết nối theo thuật toán Goeman et al. [18] để thu được hành trình MLP. Cận tỷ lệ của thuật tốn được Archer et al. chứng minh là 7.18. Thuật tốn khơng giảm cận tỷ lệ so với thuật tốn của Goeman et al. Tuy nhiên, độ phức tạp thời gian lại được cải thiện rõ rệt. Nhờ giảm được số lần gọi PCST xuống cịn O(n×log n), nên độ phức
tạp thời gian của thuật tốn là O(n3×log2n). Archer et al. cũng đưa ra thuật toán ngẫu nhiên
chỉ sử dụng O(log2n) cho lời gọi PCST và một thuật toán với cận tỷ lệ là (7.18 + ε) khi chỉ sử
dụng O((1/ε)log2n) cho lời gọi PCST. Chi tiết thuật toán của Archer et al. được trình bày
Thuật tốn 3.1. Thuật tốn Archer et al.
Đầu vào: Kn, Cij và v1 lần lượt là đồ thị đầy đủ, ma trận chi phí và đỉnh xuất phát. Đầu ra: T là hành trình MLP.
1. BEGIN
2. Thu được Tk (k = j1, j2, ..., jm (1 = j1 < j2 <....< jm = n))
từ Get_k_Tree (Kn, Cij, v1, k);
3. Chuyển các Tk thành các hành trình Euler Ck.
4. T = Kết nối Ck theo thuật toán Goemans et al. [18];
5. return T;
6. END
Thuật toán 3.2. Get_k_Tree (Kn, Cij, v1, k)
Đầu vào: Kn, Cij, v1, k lần lượt là một đồ thị đầy đủ, ma trận chi phí, đỉnh xuất phát và số
lượng đỉnh trong cây.
Đầu ra: bk, Tk là cận dưới và lời giải k-MST
1. BEGIN
2. λmin = 0; λmax = cmax; Tlo = Ø; blo = 0;
3. δ = 1 – 1/(4n – 1);
4. while (λmin ≤ λmax) do
5. λmid = (λmin + λmax ) / 2;
6. (Thi, bhi) = PCST(Kn, Cij, λmid, v1); 7. if (hi == k) then 8. bk = bhi; Tk = Thi; 9. break; 10. else 11. if (hi < k) 12. λmin= λmid;
13. if (|λmid – λ| < ((1 – δ)×cmin)/(δ×n)) then
14. bk = Interpolate(k, |Tlo|, |Thi|, blo, bhi, δ);
15. break;
16. end if
17. else
18. λmax = λmid;
19. if (|λmid – λ| < ((1 – δ)cmin)/(δ×n) then
20. bk = Interpolate(k, |Tlo|, |Thi|, blo, bhi, δ);
21. break;
22. end if
23. end if
24. Tlo = Thi; blo = bhi; λ = λmid;
25. end while
26. return bk, Tk;
27. END
Chú ý: Hàm Interpolate là hàm nội suy bk từ blo và bhi như sau:
k = αlo×|Tlo|×δ + αhi×|Thi|×δ.
αlo + αhi = 1.
Xây dựng tập các k–MST (k = 2, …, n) bằng việc sử dụng thuật toán gần đúng cho bài toán PCST giá trị phạt được thiết lập là λ [17]. Thuật toán trả về cây T và một cận dưới. Nếu λ = 0, thì kết quả trả về là một cây chứa một đỉnh gốc. Tương tự, nếu λ = cmax, thì kết quả trả về là một cây với n đỉnh. Đối với mỗi k =1, 2, …, n, thực hiện tìm kiếm nhị phân cho giá trị λ để thu được một cây với chính xác k đỉnh. Nếu thành cơng, thì ta thu được k–tree (Tk) và giá trị cận dưới. Ngược lại, ta có hai cây Tlo, Thi và hai giá trị cận dưới blo và bhi với |Tlo| < k và |Thi| >
k cho hai giá trị λlo và λhi. Nếu hai giá trị của λlo và λhi đủ gần, thì ta nội suy bk của cây có k
đỉnh từ blo và bhi theo hàm Interpolate. Chi tiết được trình bày trong Thuật toán 3.2.
Để giảm số lần gọi PCST xuống cịn O(n×log n) trong tìm kiếm nhị phân khi mà cmax/cmin = poly(n) (cmax, cmin lần lượt là chi phí của cạnh lớn nhất và nhỏ nhất), ta xóa các
đỉnh trong khoảng cách cmax/4n3 so với đỉnh gốc. Sau đó, áp dụng thuật tốn Thuật tốn 3.1 để thu được hành trình bộ phận MLP. Cuối cùng, ta bổ sung đỉnh đã bị xóa vào hành trình bộ phận này để thu được hành trình MLP.
3.1.1.4 Thuật tốn Chauhuri et al.
Hiện tại, trong hướng tiếp cận gần đúng cận tỷ lệ, các cơng trình [1, 6, 18] chỉ ra rằng chi phí tối ưu của bài tốn k–MST được xem như cận dưới cho độ trễ đỉnh thứ k trong hành trình tối ưu MLP. Có một ngoại lệ khi K.Chaudhuri et al. [9] chỉ ra rằng lời giải tối ưu của bài tốn hành trình ngắn nhất đi qua k đỉnh (ta gọi là bài toán k–troll) là một cận dưới tốt hơn cho độ trễ đỉnh thứ k trong hành trình tối ưu MLP. Tuy nhiên, bài tốn k–troll cũng khó tương tự như bài tốn k–MST, bởi vậy họ sử dụng thuật tốn tìm cây khung đi qua k đỉnh Tk có chi phí bị
chặn bởi chi phí của hành trình ngắn nhất đi qua k đỉnh. Do đó, nếu vẫn sử dụng thuật tốn kết nối của Goemans et al. [18] để kết nối các Tk (k = 2, …, n), thì ta khơng phải mất cận tỷ lệ 2 cho bài toán k–MST, bởi vậy thuật tốn có cận tỷ lệ 3.59 cho bài toán MLP.
K.Chaudhuri et al. biến đổi thuật tốn cho việc tìm k–MST có đỉnh gốc v1 và một đỉnh cuối vend với chi phí bị chặn bởi chi phí hành trình ngắn nhất đi từ v1 đến vend. Về cơ bản, ta
vẫn sử dụng thuật toán tạo ra các k-MST và cần “đốn” đỉnh cuối vend. Ta có (n – 1) khả năng cho việc “đoán” đỉnh cuối vend trong mỗi lần tạo cây k–tree (Tk ). Bởi vậy, với mỗi giá trị k, ta có tập (n – 1) k-tree khác nhau và ta chọn k-tree có chi phí nhỏ nhất là lời giải của bài tốn k- troll. Độ phức tạp thời gian của thuật toán là O(n5×log2 n). Tuy nhiên, K.Chaudhuri et al. cho rằng chỉ cần tạo ra các k–tree với O(log n) giá trị λ khác nhau. Do đó, độ phức tạp thời gian
Thuật toán 3.3. Thuật toán K.Chaudhuri et al.
Đầu vào: Kn, Cij, v1 lần lượt là một đồ thị đầy đủ, ma trận chi phí, đỉnh gốc. Đầu ra: Hành trình MLP.
1. BEGIN
2. Thu được Tk (k = j1, j2, ..., jm (1 = j1 < j2 <....< jm = n)) từ Get_best_k_troll (Kn, Cij, v1, k);
3. Chuyển các Tk thành các hành trình Euler Ck.
4. T = Kết nối Ck theo thuật toán Goemans et al. [18];
5. Return T;
6. END
Thuật toán 3.4. Get_best_k_troll (Kn, Cij, v1, k)
Đầu vào: Kn, Cij, v1 lần lượt là một đồ thị đầy đủ, ma trận chi phí, đỉnh gốc và số lượng đỉnh
trong cây.
Đầu ra: Tk là cây cần tìm.
1. BEGIN 2. sT = Ø; 3. bT = +∞; Tk-troll = Ø; 4. for (i = 1; i ≤ n – 1; i ++) do 5. vend = {vKn | v # v1 và v sT}; 6. sT = sT {vend};
7. Tk = Get_k_troll (Kn, Cij, v1, vend, k);
8. if (bT > c(Tk)) 9. Tk-troll = Tk; bT = c(Tk); 10. end if 11. end for 12. return Tk-troll; 13. END
Hàm Get_k_troll bao gồm các bước giống với hàm Get_k_tree trong Thuật toán 3.2. Tuy nhiên, hàm Get_k_troll gọi thủ tục PCST với đỉnh cuối vend. Mỗi đỉnh dự đoán vend tạo ra một Tk . Ta chọn Tk với chi phí nhỏ nhất bởi hàm Get_best_k_troll trong Thuật tốn 3.4. Để kết nối các Tk này, ta sử dụng thuật toán kết nối của Goemans et al. [18]. Chi tiết thuật tốn được trình bày trong Thuật tốn 3.3.
3.1.1.5 Thuật toán Arora et al.
Arora et al. [3] cho rằng có thể phân rã hành trình MLP thành các đoạn sao cho bất kỳ sự thay đổi nào trong mỗi đoạn không ảnh hưởng nhiều đến tổng độ trễ của hành trình MLP. Sau đó, thay thế mỗi đoạn bởi hành trình người du lịch tối ưu (optimum traveling salesman tour). Gọi
hành trình người du lịch tối ưu để thu được hành trình MLP có độ trễ nhiều nhất là (1 +
ε)×OPT, với ε > 0.
Arora et al. đã sử dụng ý tưởng này để xây dựng lược đồ xấp xỉ giải bài toán MLP trong khơng gian euclidean. Thuật tốn của Arora et al. bao gồm các bước: Ban đầu, n đỉnh
của đồ thị được bao phủ bởi một ô vuông (boundingbox) như Hình 3.1. Ta đặt một lưới LxL trên ơ vng đó và di chuyển các đỉnh trong ơ vuông đến điểm lưới gần nhất. Theo Arora et al., bước này còn được gọi là bước làm trịn (well_rounded) và độ trễ hành trình tối ưu MLP sau bước làm trịn nhiều nhất bằng O(δ×OPT) (0 < δ < ε và OPT là độ trễ của hành trình tối
ưu MLP trước khi làm tròn). Tiếp theo, thao tác đệ quy chia nhỏ lưới LxL thành các ô vuông (square) có kích thước nhỏ hơn. Ta dừng việc chia khi mà mỗi ô vuông chứa nhiều nhất một đỉnh của đồ thị ban đầu. Trong Hình 3.2, ta coi ô vuông ban đầu là ô vuông mức 0 và các ô vuông tại mỗi lần chia nhỏ sẽ ứng với ô vuông mức 1, 2, … Việc phân chia này tạo ra một cây (quadtree) có gốc là hình vng mức 0 (boundingbox) và các con của cây tại mỗi mức cũng là các hình vng được được tạo thành bởi q trình chia nhỏ như Hình 3.2. Mỗi nút của cây có bốn con và cây có O(L2) nút và độ sâu là O(log L). Trên mỗi cạnh ơ vng, có một tập các điểm gọi là portal. Mỗi ơ vng có bốn portal ở bốn góc và
n log
portal cách đều
nhau trên mỗi cạnh. Ta định nghĩa một hành trình–(m, k) ((m, k)–light tour) là một hành trình đi qua mỗi cạnh của mỗi ơ vng trong một quadtree nhiều nhất k lần và chỉ tại một trong m portal của nó như Hình 3.3. Phương pháp quy hoạch động ở bước cuối cùng được thực hiện để tìm một hành trình–(c×log n/ε, f×log n/ε) (c, f là hằng số và ε > 0) đi qua n đỉnh. Để ghi nhận lời giải, ta xây dựng một bảng tra cứu (tableMatrix) cho mỗi ô vuông (square) theo chiến lược từ dưới lên (bottom up). Khi xét một ô vuông của quadtree, cần liệt kê tất cả các khả năng cho ra một crossing (Hình 3.4) và tìm trong bảng tra cứu những hành trình bộ phận (hành trình đi qua k đỉnh và k < n) nào có thể ghép nối với nó để tạo thành một hành trình
mới. Kiểm tra xem hành trình mới này có là hành trình–(c×log n/ε, f×log n/ε). Nếu đúng thì cập nhập vào trong bảng tra cứu. Khi kết thúc thuật toán quy hoạch động, có nhiều hơn một hành trình đi qua n đỉnh được tạo thành. Hành trình với độ trễ là nhỏ nhất được chọn là lời giải bài tốn. Theo Arora et al. thì độ trễ hành trình thu được nhiều nhất bằng (1 + ε)×OPT. Chi tiết thuật tốn được trình bày từ Thuật tốn 3.5 đến Thuật tốn 3.9.
Hình 3. 1 Hình vng (bounding box) bao phủ các đỉnh
Hình 3. 3 Tập các portal
Hình 3. 4 Minh họa crossing đi qua các portal
Thuật toán 3.5. Thuật toán Arora et al.
Đầu vào: Kn, Cij, f, c lần lượt là đồ thị đầy đủ, ma trận chi phí, và các hằng số. Đầu ra: Hành trình MLP tốt nhất.
1. BEGIN
2. boundingBox = Well_rounded (Kn);
3. squareMatrix = Construct_Shifted_Quadtree (boundingBox);
4. tableMatrix = DynamicProgramming(squareMatrix, f, c);
5. return hành trình qua n đỉnh có độ trễ nhỏ nhất từ tableMatrix;
6. END
Thuật toán 3.6. well_rounded (Kn) Đầu vào: Kn là đồ thị đầy đủ.
Đầu ra: boundingBox là hình vng (LxL).
1. BEGIN
2. L = O(n);
3. Chia hình vng thành các ơ vng cách đều g = ϴ(δ×L/n2) (0 < δ < ε); 4. Chuyển mỗi đỉnh của Kn đến điểm lưới gần nhất;
5. Chia độ dài các cạnh trong Kn cho g;
6. return boundingBox;
Thuật toán 3.7. Construct_Shifted_Quadtree (boundingBox) Đầu vào: Một well-rounded boundingBox.
Đầu ra: squareMatrix lưu trữ một tập các Quadtrees.
1. BEGIN
2. Chia boundingBox cho đến tận khi mỗi hình vng chứa nhiều nhất một đỉnh để tạo
thành các quadtree;
3. Sinh hai số ngẫu nhiên a, b (0 a, b < L);
4. Dịch các quatree lần lượt theo tọa độ x và tọa độ y bởi đại lượng a và b;
5. return quadtrees;
6. END
Thuật toán 3.8. CalculateMatrix (sq: square, f, c)
Đầu vào: sq, f, c lần lượt là hình vng, các hằng số cho trước.
1. BEGIN
2. Portals = sq.getPortals();
3. Crossing = doCrosings(Portals, sq);
4. for i := 0 to Crosings.getSize() do
5. Tìm trong tableMatrix những hành trình bộ phận thỏa crossing hiện tại.
6. Kết nối chúng để tạo thành một hành trình bộ phận mới.
7. if (hành trình này là hành trình–(clogn/ε, flogn/ε))
8. Lưu trữ vào trong tableMatrix;
9. end for
10. END
Thuật toán 3.9. DynamicProgramming (squareMatrix: q, f, c) Đầu vào: squareMatrix là một tập các quadtree
Đầu ra: Biến ma trận tồn cục lưu trữ các hành trình (clog n/ε, flog n/ε).
1. BEGIN 2. leaves = q.leaves(); 3. squares = q.getSquares(); 4. for i := 0 to leaves.getSize() do 5. calculateMatrix(leaves[i], f, c); 6. end for
7. for i:= 0 to squares.getSize() do
8. calculateMatrix(squares[i], f, c);
9. end for
10. return tableMatrix;
11. END
3.1.2 Kết quả thực nghiệm
Để đánh giá hiệu quả của thuật toán, hai thực nghiệm được tiến hành. Dữ liệu trong thực nghiệm đầu tiên bao gồm các file dữ liệu nhỏ trong bộ dữ liệu ngẫu nhiên từ 1 đến 3 và bộ dữ
liệu thực 2. Thực nghiệm thứ hai được tiến hành với các file dữ liệu lớn trong bộ dữ liệu thực 1 và bộ dữ liệu ngẫu nhiên 3. Đối với các file dữ liệu nhỏ, lời giải tối ưu từ thuật toán đúng cho phép ta đánh giá chính xác hiệu quả của các thuật tốn. Đối với các file dữ liệu lớn, khi mà lời giải tối ưu chưa được biết đến, hiệu quả của các thuật toán chỉ được đánh giá một cách tương đối.
Các thuật toán được sử dụng trong các thực nghiệm gồm thuật toán của Blum et al. (BA), Goemans et al. (GKA), Archer et al. (AA), Chauhuri et al. (KA) và Arora et al. (AK). Đối với thuật toán của Arora et al., chúng tơi thực thi thuật tốn cận tỷ lệ (1 + ε) với ε > 0 cho các file dữ liệu thỏa khơng gian euclidean và thuật tốn cận tỷ lệ 11.65 cho các file dữ liệu phi euclidean. Ta ký hiệu: LB, L và T lần lượt là cận dưới, độ trễ lời giải và thời gian chạy
chạy tính bằng phút của các thuật tốn. Trong các bảng, các giá trị của các cột là kết quả của các thuật toán gần đúng bao gồm cận tỷ lệ p, LB và T. Trong các bảng từ 3.1 đến 3.2, cận tỷ lệ p L OPT / (OPT là lời giải tối ưu có được từ thuật toán đúng trong chương 2). Trong các bảng 3.3 và 3.4, do chưa biết lời giải tối ưu của các file dữ liệu lớn nên chúng ta sử dụng cận tỷ lệ như sau L fA(fA là cận dưới của giá trị tối ưu được lấy từ Archer et al. [1]) và cũng