Làm cách nào để tạo DFA từ biểu thức chính quy mà không sử dụng NFA?


12

Mục tiêu là tạo DFA từ một biểu thức thông thường và sử dụng "exp thông thường> NFA> chuyển đổi DFA" không phải là một tùy chọn. Làm thế nào một người nên đi về làm điều đó?

Tôi đã hỏi câu hỏi này với giáo sư của chúng tôi nhưng ông nói với tôi rằng chúng ta có thể sử dụng trực giác và vui lòng từ chối đưa ra bất kỳ lời giải thích nào. Vì vậy, tôi muốn hỏi bạn.

"Chuyển đổi thường xuyên> NFA> chuyển đổi DFA" không phải là một tùy chọn vì việc chuyển đổi như vậy mất rất nhiều thời gian để chuyển đổi một biểu thức chính quy khá phức tạp. Ví dụ: đối với một regex nhất định "regex> NFA> DFA" mất 1 giờ cho một con người. Tôi cần chuyển đổi regex sang DFA trong vòng chưa đầy 30 phút.


2
Bạn cần cung cấp thêm bối cảnh. Thuật toán (không chính thức) nào bạn hiện đang sử dụng để dịch các biểu thức thông thường? Nó có thể hữu ích để giải thích quá trình của bạn với một ví dụ như a(a|ab|ac)*a+. Bạn có thể dịch trực tiếp điều đó sang NDFA mà bạn giảm xuống thành DFA hoặc bạn có thể bình thường hóa nó thành thứ gì đó ánh xạ ngay lập tức sang DFA.
amon

Bạn có phải làm điều đó trên các ví dụ cụ thể bằng bất kỳ phương tiện nào, hoặc bạn phải cung cấp một quy trình chung. Để được áp dụng bởi máy tính?
babou 28/03/2015

Câu trả lời:


18

Vì bạn muốn "chuyển đổi regex thành DFA trong vòng chưa đầy 30 phút", tôi cho rằng bạn đang làm việc bằng tay trên các ví dụ tương đối nhỏ.

Trong trường hợp này, bạn có thể sử dụng thuật toán của Brzozowski , tính toán trực tiếp máy tự động Nerode của ngôn ngữ (được biết là bằng với máy tự động xác định tối thiểu của nó). Nó dựa trên tính toán trực tiếp của các đạo hàm và nó cũng hoạt động cho các biểu thức chính quy mở rộng cho phép giao nhau và bổ sung. Hạn chế của thuật toán này là nó yêu cầu kiểm tra tính tương đương của các biểu thức được tính trên đường đi, một quá trình tốn kém. Nhưng trong thực tế, và cho các ví dụ nhỏ, nó rất hiệu quả.[1]

Chỉ tiêu còn lại . Hãy là một ngôn ngữ của A * và để u là một từ. Sau đó u - 1 L = { v A * | u v L } Ngôn ngữ u - 1 L được gọi là một thương trái (hoặc trái đạo hàm ) của L .LMột*bạn

bạn-1L= ={vMột*|bạnvL}
bạn-1LL

Máy tự động Nerode . Các automaton Nerode của là automaton xác định A ( L ) = ( Q , A , , L , F ) nơi Q = { u - 1 L | u A * } , F = { u - 1 L | u L } và chức năng chuyển tiếp được xác định, đối với mỗi một LMột(L)= =(Q,Một,,L,F)Q= ={bạn-1L|bạnMột*}F= ={bạn-1L|bạnL} , theo công thức ( u - 1 L ) một = một - 1 ( u - 1 L ) = ( u một ) - 1 L Cảnh giác với những nét khá trừu tượng này. Mỗi tiểu bang của A là một thương trái của L bằng một từ, và do đó là một ngôn ngữ của A * . Tình trạng ban đầu là ngôn ngữ L , và các thiết lập của tiểu bang cuối cùng là tập hợp của tất cả các thương số bên trái của L bằng một lời L .mộtMột

(bạn-1L)một= =một-1(bạn-1L)= =(bạnmột)-1L
MộtLMột*LLL

một,b

a11=0a1b={1if a=b0if aba1(L1L2)=a1L1u1L2,a1(L1L2)=a1L1u1L2,a1(L1L2)=a1L1u1L2,a1L=(a1L)L
a1(L1L2)={(a1L1)L2si 1L1,(a1L1)L2a1L2si 1L1

L=(a(ab))(ba)

11L=L=L1a1L1=(ab)(a(ab))=L2b1L1=a(ba)=L3a1L2=b(ab)(a(ab))(ab)(a(ab))=bL2L2=L4b1L2=a1L3=(ba)=L5b1L3=a1L4=a1(bL2L2)=a1L2=L4b1L4=b1(bL2L2)=L2b1L2=L2a1L5=b1L5=a(ba)=L3
Máy tự động tối thiểu

[1]

Chỉnh sửa . (Ngày 5 tháng 4 năm 2015) Tôi mới phát hiện ra một câu hỏi tương tự: Thuật toán nào tồn tại để xây dựng một DFA nhận ra ngôn ngữ được mô tả bởi một biểu thức chính quy? đã được hỏi về cstheory. Câu trả lời một phần giải quyết các vấn đề phức tạp.


Bạn có thể nói thêm về sự phức tạp của thuật toán này?
babou 28/03/2015

@babou Chuyển đổi RE thành DFA rất khó, vì vậy nó chắc chắn theo cấp số nhân.
jmite

Điều này có lẽ nên đi vào câu trả lời. OP bắt đầu với "các công trình tiêu chuẩn thông qua NFA quá chậm" và một phần của câu trả lời dường như là "xui xẻo, thực sự không có giải pháp nhanh". Vẫn còn để thảo luận liệu điều này ở đây là tốt hơn so với xây dựng tiêu chuẩn. (cc @jmite)
Raphael

@jmite Vâng, tôi đã mong đợi điều đó. Lý do cho câu hỏi của tôi là tại sao cách xây dựng DFA này nên được xem là dễ dàng hơn. (lưu ý: hệ thống mất cả ngày để thông báo cho tôi về câu trả lời @ jmite).
babou

2

J.-E. Pin cung cấp câu trả lời tốt hơn về mặt hình thức và tính đầy đủ, nhưng tôi nghĩ có điều gì đó để nói về "trực giác" mà giáo sư của bạn đang ám chỉ.

Trong hầu hết các trường hợp này, cách dễ nhất là nhìn vào biểu thức chính quy, hiểu ngôn ngữ mà nó chấp nhận, sau đó sử dụng sự sáng tạo / thông minh của bạn để xây dựng một DFA chấp nhận ngôn ngữ đó.

Không có cách nào đơn giản để làm điều này, ngoài các thuật toán mà người khác đã đưa ra, nhưng đây là một số hướng dẫn có thể hữu ích.

  1. Hãy tự hỏi mình, tôi có thể viết một chương trình chấp nhận RE này chỉ bằng các biến số nguyên boolean hoặc rất nhỏ không? Sau đó viết chương trình đó và chuyển đổi nó thành DFA trong đó có trạng thái cho mọi kết hợp các giá trị.

  2. Tìm kiếm các phần của biểu thức chính quy mà bạn biết bạn có thể chấp nhận một cách xác định, trong đó bạn biết "Nếu tôi thấy điều này, thì tôi phải khớp với phần này của RE." Sẽ không có hàng tấn trong số này, nhưng việc xác định các phần này có thể hiển thị các phần sẽ dễ dàng tạo DFA, vì vậy bạn có thể dành nhiều thời gian hơn cho các phần thực sự đòi hỏi tính không xác định.

  3. Cấu trúc tập hợp con cho NFA-> DFA không thực sự phức tạp về thuật toán. Vì vậy, nếu đây là một bài tập, không phải là một câu hỏi thi, có thể nhanh hơn khi chỉ viết mã triển khai và để chương trình của bạn chuyển đổi NFA thành DFA. Nếu bạn đã sử dụng mã của riêng mình, sẽ không có bất kỳ vấn đề nào về đạo đức.

P= =NP= =PSPMộtCE

Cố gắng "nhìn về phía trước", cắt các góc khi bạn có thể sử dụng trực giác của mình ở những nơi mà thuật toán sẽ yêu cầu nhiều bước nhưng kết quả của nó rất rõ ràng.


-2

Mặc dù đây không phải là cách chính xác nhưng nó hoạt động hầu hết thời gian.

Bước đầu tiên : Tìm chuỗi nhỏ nhất có thể được chấp nhận bởi Biểu thức chính quy. Bước thứ hai : Vẽ các trạng thái cần thiết với giao dịch của máy chấp nhận chuỗi tối thiểu. Bước thứ ba : Đối với tất cả các trạng thái, hãy vẽ các giao dịch bảng chữ cái còn lại.

Ví dụ: Biểu thức chính quy (0 + 1) * 1 "Chuỗi kết thúc bằng 1" Bước 1: Chuỗi nhỏ nhất: 1 Bước 2: hai trạng thái Q0 và Q1. có giao dịch 1 từ Q0 đến Q1. và Q1 là trạng thái chấp nhận. Bước 3: đối với giao dịch Q0 Trạng thái Q0 1 là Q1. Bây giờ thực hiện 0 giao dịch trong chính Q0. Đối với Q1 Nhà nước giao dịch Q1 1 sẽ vẫn trong Q1. Và 0 giao dịch sẽ đi vào Q0.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.