Giải thuật phát hiện chu trình

Một phần của tài liệu Khung Cộng Tác Đa Dụng Trong Môi Trường Tính Toán Lưới (Trang 92)

B. Giải thuật phát hiện các mẫu có cấu trúc đầy đủ

B.2 Giải thuật phát hiện chu trình

Phần này sẽ tóm tắt lại các tư tưởng chính của một số giải thuật đã được đề xuất trước đây nhằm phát hiện các chu trình trong đồ thị có hướng. Chi tiết của các giải thuật này có thể được tham khảo trong [90][48].

Cho trước đồ thị có hướng G=(V,E) với V và E tương ứng là tập các đỉnh và tập các cạnh của G. Một chu trình (circle) (cũng còn gọi là chu trình cơ bản (elementary circuit)) là

một đường dẫn (path) (v1,v2,…,vk-1,vk), sao cho v1=vk, và với mọi i=1..(k-1), (vi,vi+1) E. Để

có một giải thuật hiệu quả cho việc tìm kiếm tất cả các chu trình, hai vấn đề sau đây cần được giải quyết:

1. Thứ nhất: làm thế nào để tìm được toàn bộ các chu trình.

2. Thứ hai: làm thế nào để tránh được một cách tối đa các thao tác lặp lại không cần thiết trong khi tìm kiếm. Có một số kiểu thao tác lặp không cần thiết như thăm các cạnh hay các nút nhiều lần, hay thậm chí thăm cả chu trình nhiều lần.

Để giải quyết vấn đề thứ nhất, tất cả các đường dẫn mà có thể chứa các chu trình cần phải được kiểm tra. Tuy nhiên, yêu cầu này lại dễ gây ra vấn đề thứ hai, nếu không có những biện pháp thích hợp.

Đa số các giải thuật tìm kiếm chu trình đều sử dụng chiến lược tìm theo chiều sâu (depth-first search (DFS)), bởi vì tính chất chạy theo đường dẫn (path-following) của chiến

lược này giúp cho việc kiểm tra sự tồn tại của chu trình, cũng như xác định tất cả các thành phần (cạnh và nút) trong các chu trình tìm được là tương đối dễ dàng. Một ưu điểm nữa của chiến lược này là mỗi phép tìm kiếm, nó chỉ thăm mỗi cạnh đúng một lần. Tuy nhiên, chiến lược này cũng có một số hạn chế. Thứ nhất, mỗi phép tìm kiếm có thể phải thăm một nút nhiều lần. Thứ hai, với tính chất chạy theo đường dẫn dễ dẫn đến việc thăm một chu trình nhiều lần.

Sử dụng chiến lược tìm theo chiều sâu, giải thuật của Tarjan [90] lặp lại phép tìm kiếm nhiều lần. Mỗi lần tìm, xuất phát từ một đỉnh s, tất cả các chu trình chứa s sẽ được tìm. Để tránh phải lặp lại việc tìm kiếm cho các đường dẫn và các chu trình đã bị tìm trước rồi, trước khi bắt đầu tìm kiếm, tất cả các đỉnh sẽ được đánh số từ 1 đến n (với n là số đỉnh của đồ thị). Sau đó, ở mỗi phép tìm kiếm từ đỉnh s, nó chỉ tìm trong những đường dẫn (v1, v2, …, vk) sao cho v1=s, và ∀ i=2..k, (vi > v1). Để lưu trữ các đường dẫn đã thăm, giải thuật này sử dụng hai ngăn xếp (stacks): point stack để lưu đường dẫn đang thăm, mark stack để chứa các đỉnh đã thăm. Để tránh việc thăm lại các đường dẫn đã được thăm rồi, hai ngăn xếp này sẽ được làm rỗng trước mỗi phép thăm. Tuy nhiên, giải pháp này lại có thể dẫn đến nhiều phép duyệt đường dẫn không cần thiết ở các phép duyệt kế tiếp, bởi vì có nhiều phần trong các đường dẫn sẽ được tìm lại đã được thăm ở các phép tìm trước đó. Một nguồn nữa cho các phép duyệt không cần thiết là việc chọn nhầm đỉnh bắt đầu tìm kiếm – là đỉnh mà không nằm trong bắt kỳ chu trình nào. Giải thuật này chọn đỉnh bắt đầu hoàn toàn ngẫu nhiên, nên khả năng chọn nhầm không hề nhỏ. Chính vì những hạn chế trên mà độ phức tạp của giải thuật này trong trường hợp xấu nhất, được tính toán bởi Johnson [48], là O(n.e.(c+1)), với n là số đỉnh, e là số cạnh và c là số chu trình.

Dựa trên giải thuật của Tarjan, giải thuật của Johnson [48] có một cải tiến quan trọng nhằm tránh việc chọn nhầm đỉnh bắt đầu. Trong giải thuật này, đỉnh bắt đầu được chọn là đỉnh nhỏ nhất trong một thành phần liên thông mạnh (strongly connected component)- là thành phần luôn có ít nhất một chu trình. Nhờ cải tiến này mà độ phức tạp của giải thuật chỉ còn O((n+e).(c+1)), tốt hơn khá nhiều so với giải thuật của Tarjan.

Một phần của tài liệu Khung Cộng Tác Đa Dụng Trong Môi Trường Tính Toán Lưới (Trang 92)

Tải bản đầy đủ (DOCX)

(168 trang)
w