Có một số phương pháp để thực hiện chuyển đổi từ automata hữu hạn sang biểu thức thông thường. Ở đây tôi sẽ mô tả một người thường được dạy ở trường rất trực quan. Tôi tin rằng nó được sử dụng nhiều nhất trong thực tế. Tuy nhiên, viết thuật toán không phải là một ý tưởng tốt.
Phương pháp loại bỏ nhà nước
Thuật toán này là về việc xử lý đồ thị của máy tự động và do đó không phù hợp lắm với các thuật toán vì nó cần các nguyên hàm đồ thị như ... loại bỏ trạng thái. Tôi sẽ mô tả nó bằng cách sử dụng nguyên thủy cấp cao hơn.
Ý tưởng chính
Ý tưởng là xem xét các biểu thức chính quy trên các cạnh và sau đó loại bỏ các trạng thái trung gian trong khi vẫn giữ các nhãn cạnh nhất quán.
Các mô hình chính có thể được nhìn thấy trong các hình sau đây. Đầu tiên có nhãn giữa là các biểu thức chính quy e , f , g , h , i và chúng tôi muốn xóa q .p,q,re,f,g,h,iq
Sau khi xóa, chúng ta kết hợp lại với nhau (trong khi bảo tồn các cạnh khác giữa p và r nhưng điều này không được hiển thị trên này):e,f,g,h,ipr
Thí dụ
Sử dụng ví dụ tương tự như trong câu trả lời của Raphael :
chúng tôi liên tiếp xóa :q2
và sau đó :q3
sau đó chúng ta vẫn phải áp dụng một ngôi sao trên biểu thức từ đến q 1 . Trong trường hợp này, trạng thái cuối cùng cũng là ban đầu, vì vậy chúng tôi thực sự chỉ cần thêm một ngôi sao:q1q1
(ab+(b+aa)(ba)∗(a+bb))∗
Thuật toán
L[i,j]
là biểu thức chính của ngôn ngữ từ đến q j . Đầu tiên, chúng tôi loại bỏ tất cả các cạnh:qiqj
for i = 1 to n:
for j = 1 to n:
if i == j then:
L[i,j] := ε
else:
L[i,j] := ∅
for a in Σ:
if trans(i, a, j):
L[i,j] := L[i,j] + a
Bây giờ, nhà nước loại bỏ. Giả sử chúng ta muốn xóa trạng thái :qk
remove(k):
for i = 1 to n:
for j = 1 to n:
L[i,i] += L[i,k] . star(L[k,k]) . L[k,i]
L[j,j] += L[j,k] . star(L[k,k]) . L[k,j]
L[i,j] += L[i,k] . star(L[k,k]) . L[k,j]
L[j,i] += L[j,k] . star(L[k,k]) . L[k,i]
star(ε)=ε
e.ε=e
∅+e=e
∅.e=∅
∅εq k q j q kqiqkqjqk
Bây giờ, sử dụng như thế nào remove(k)
? Bạn không nên loại bỏ các trạng thái cuối cùng hoặc ban đầu một cách nhẹ nhàng, nếu không bạn sẽ bỏ lỡ các phần của ngôn ngữ.
for i = 1 to n:
if not(final(i)) and not(initial(i)):
remove(i)
Nếu bạn chỉ có một trạng thái cuối cùng và một trạng thái ban đầu thì biểu thức cuối cùng là:q sqfqs
e := star(L[s,s]) . L[s,f] . star(L[f,s] . star(L[s,s]) . L[s,f] + L[f,f])
Nếu bạn có một vài trạng thái cuối cùng (hoặc thậm chí là trạng thái ban đầu) thì không có cách đơn giản nào để hợp nhất những trạng thái này, ngoài việc áp dụng phương pháp đóng bắc cầu. Thông thường đây không phải là vấn đề bằng tay nhưng điều này thật bất tiện khi viết thuật toán. Một cách giải quyết đơn giản hơn nhiều là liệt kê tất cả các cặp và chạy thuật toán trên biểu đồ (đã loại bỏ trạng thái) để có được tất cả các biểu thức giả sử là trạng thái ban đầu duy nhất và là trạng thái cuối cùng duy nhất trạng thái, sau đó thực hiện liên kết của tất cả .e s , f s f e s , f(s,f)es,fsfes,f
Điều này và thực tế là điều này đang sửa đổi các ngôn ngữ linh hoạt hơn phương thức đầu tiên làm cho nó dễ bị lỗi hơn khi lập trình. Tôi đề nghị sử dụng bất kỳ phương pháp khác.
Nhược điểm
Có rất nhiều trường hợp trong thuật toán này, ví dụ để chọn nút nào chúng ta nên loại bỏ, số trạng thái cuối cùng ở cuối, thực tế là trạng thái cuối cùng cũng có thể là ban đầu, v.v.
Lưu ý rằng bây giờ thuật toán được viết, nó rất giống với phương thức đóng bắc cầu. Chỉ có bối cảnh của việc sử dụng là khác nhau. Tôi không khuyên bạn nên thực hiện thuật toán, nhưng sử dụng phương pháp để làm điều đó bằng tay là một ý tưởng tốt.