Tạo một tập hợp các chuỗi có độ dài tối thiểu, cùng nhau, gọi mọi sản phẩm của ngôn ngữ không ngữ cảnh


7

Vấn đề (tl; dr)

Đưa ra một ngữ pháp không có ngữ cảnh, , hãy tìm một tập hợp các chuỗi đưa qua mọi sản phẩm mà nó có ít nhất một lần.GG

Làm thế nào và nhanh như thế nào nó có thể được thực hiện?

Lý lịch

Tôi đang làm việc trên một trình biên dịch có trình phân tích cú pháp được triển khai với một công cụ tương tự như Yacc + Antlr. Tôi đã viết hầu hết mã trình phân tích cú pháp và tôi muốn tạo một số mã của ngôn ngữ đối tượng để gọi mọi sản phẩm ngữ pháp ít nhất một lần để tôi có thể cung cấp mã cho trình phân tích cú pháp và đảm bảo rằng không có gì sai .

Đối với thử nghiệm tốt, thứ tôi thực sự thích là một tệp thử nghiệm ngắn có một sản phẩm cụ thể "đang thử nghiệm" - vì vậy, đối với mỗi quy tắc sản xuất, tôi muốn tạo một chuỗi tối thiểu lấy trình phân tích cú pháp từ bắt đầu trạng thái, thông qua việc sản xuất đang được thử nghiệm, đến một tập hợp các thiết bị đầu cuối.

Phương pháp khả thi

Tôi tưởng tượng có một giải pháp tao nhã sử dụng lý thuyết đồ thị, nhưng tôi không chắc nó là gì. Tôi chỉ muốn sử dụng thuật toán của Dijkstra để tìm các đường dẫn ngắn nhất thông qua một số cấu trúc phù hợp, nhưng tôi nghĩ rằng một chuỗi được phân tích cú pháp bởi ngữ pháp không ngữ cảnh trong cấu trúc cây chứ không phải là một đường dẫn, vì vậy tôi không biết làm thế nào để làm việc đó .

Tôi nghĩ rằng có thể có một cách thông minh để đặt nó như là một vấn đề lưu lượng mạng. Một cái gì đó như thế này: lấy một biểu đồ có một đỉnh cho mọi ký hiệu (terminal và nonterminal) và một đỉnh cho mỗi sản xuất. Nếu một nonterminal có sản xuất, hãy thêm một cạnh được định hướng từ nonterminal vào sản xuất. Nếu một sản phẩm tạo ra một biểu tượng, thêm một cạnh được định hướng từ sản xuất vào biểu tượng. Thêm một nguồn có công suất và gắn nó vào đỉnh tương ứng với biểu tượng bắt đầu. Thêm một bồn rửa với công suất vô hạn và gắn nó vào mỗi thiết bị đầu cuối.c

Nếu một nonterminal có một cung tròn có công suất , hãy thêm một cung từ nonterminal vào mỗi sản phẩm của nó có công suất . Nếu một sản phẩm có một cung tròn có công suất và nó có một cung ngoài tới nonterminals, hãy thêm một cung có công suất từ sản xuất cho mỗi nonterminal.kkknkn

Sau đó chạy một số thuật toán lưu lượng tối đa trên mạng và để các sản phẩm "nhỏ giọt" từ biểu tượng bắt đầu đến các thiết bị đầu cuối. Bạn nên kết thúc với một luồng xuất phát từ nguồn của mình và bạn có thể trả về tất cả các thiết bị đầu cuối mà bạn đạt được với một luồng khác không dưới dạng chuỗi kết quả của bạn. Sau đó, bạn kết thúc với độ phức tạp thời gian như cho mỗi lần chạy, trong đó là tổng của số lượng thiết bị đầu cuối và số không có trong ngữ pháp của bạn - không quá tệ.cO(n3)n

Tuy nhiên, tôi vẫn không thực sự chắc chắn biểu đồ này trông như thế nào: Tôi nghĩ rằng nó cần phải là vô hạn và tôi không chắc liệu bạn có thể tìm thấy lưu lượng tối đa của mạng lưu lượng vô hạn hay không. Trước đó, tôi không chắc chắn làm thế nào để "loại bỏ" một sản phẩm khỏi sự cân nhắc để tôi được đảm bảo có được một sản phẩm mới cho mỗi lần chạy thử.

Tôi googled và tôi không thể tìm thấy bất cứ điều gì. Có một giải pháp tốt cho vấn đề này?


1
Ngữ pháp đầu vào có thể mơ hồ? Nếu vậy, một chuỗi có tính cho tất cả các sản phẩm trong tất cả các sản phẩm không? Chúng ta có thể giả sử rằng ngữ pháp bị giảm, tức là không chứa các quy tắc "ngõ cụt" (mọi quy tắc đều có thể truy cập được từ biểu tượng bắt đầu và có một bên phải có thể rút ra một từ)?
Raphael

@Raphael Ngữ pháp cụ thể mà tôi đang làm việc không rõ ràng ở một vài nơi nhỏ nhưng có thể bỏ qua vì đơn giản nếu cần thiết. Tôi muốn thay vào đó là một chuỗi mơ hồ không được tính cho tất cả các dẫn xuất có thể có của nó, vì mục đích của tôi là buộc trình phân tích cú pháp đánh vào mọi nhánh mã, nhưng như tôi nói rằng tôi nhận ra điều đó là không thể. Ngữ pháp bị giảm.
Patrick Collins

Hãy thử nó lạc hậu. Xây dựng một bộ quy tắc trong đó phía bên phải (RHS) là một chuỗi đầu cuối (bao gồm từ trống, là một chuỗi trống của các thiết bị đầu cuối). Sau đó, lần lượt xem xét tất cả các quy tắc còn lại, để xem liệu một quy tắc có RHS có thể được dẫn xuất thành chuỗi đầu cuối với các quy tắc trong tập hợp của bạn không ... và cố gắng tự hoàn thành việc này. Mặc dù vậy, có hai nhận xét: Tôi rất ngạc nhiên khi bạn lập trình một trình phân tích cú pháp "tương tự như Yacc + Antlr" với kiến ​​thức hạn chế về ngữ pháp không ngữ cảnh. Điểm thứ hai là tôi nghi ngờ bài kiểm tra của bạn là đủ: các quy tắc có thể tương tác trong quá trình phân tích cú pháp.
babou

Chắc chắn, bảo hiểm mã được biết đến là một chiến lược thử nghiệm rất thô sơ. Hơn nữa, bạn có một ngôn ngữ lập trình với cú pháp mơ hồ? Trời ơi.
Raphael

@Raphael Ngữ pháp mơ hồ cho một ngôn ngữ lập trình không làm phiền tôi. Tôi đã ủng hộ họ trong nhiều năm. Quốc phòng Hoa Kỳ đã sử dụng một trong khoảng 30 năm. Nhưng, công nghệ phụ thuộc vào mức độ mơ hồ và cách xử lý sự mơ hồ. Nếu công nghệ là Yacc + Antlr, thì trình phân tích cú pháp sẽ hành xử như thể ngôn ngữ không rõ ràng: nếu buộc phải lựa chọn. Các công nghệ khác có thể giữ sự mơ hồ. Nhưng tôi vẫn bị làm phiền bởi thực tế tất cả đòi hỏi một mức độ hiểu biết mà dường như không có trong câu hỏi.
babou

Câu trả lời:


3

Tóm lại

Không biết đủ tài liệu, tôi đã tìm ra một giải pháp được trình bày trong phần tiếp theo, cùng với một bằng chứng cho phần khó nhất. Một khi tôi biết những gì cần thiết, tôi có thể tìm kiếm tài liệu cho những ý tưởng phù hợp. Dưới đây là một bản trình bày nhanh về thuật toán, dựa trên tài liệu, về cơ bản giống như tôi đã phát triển.

Điều đầu tiên cần làm là tìm một chuỗi thiết bị đầu cuối có kích thước tối thiểu cho mọi không đầu cuối của ngữ pháp. Điều này có thể được thực hiện bằng cách sử dụng phần mở rộng của Knuth cho conc-hoặc đồ thị (còn được gọi là ngữ pháp CF) và và hoặc đồ thị của thuật toán đường đi ngắn nhất của Dijkstra . Ví dụ B trong bài báo của Knuth làm những gì cần thiết, gần như.σ(U)U

Trên thực tế, Knuth chỉ tính toán độ dài của các chuỗi đầu cuối này, nhưng khá dễ dàng để sửa đổi thuật toán của anh ta để thực sự tính toán một chuỗi đầu cuối như vậy cho mỗi không đầu cuối (như tôi làm trong phiên bản của mình bên dưới) . Chúng tôi cũng định nghĩa cho mọi thiết bị đầu cuối và chúng tôi mở rộng như bình thường thành một phép đồng hình chuỗi.σ(U)Uσ(a)=aaσ

Sau đó, chúng tôi xem xét một biểu đồ có hướng trong đó các thiết bị đầu cuối không phải là các nút và có một cung nếu có quy tắc . Nếu một số quy tắc như vậy có thể tạo ra cùng một cung , chúng ta sẽ giữ một cung sao cho độ dàilà tối thiểu Vòng cung được gắn nhãn theo quy tắc đó và độ dài tối thiểu đó trở thành trọng lượng của vòng cung.(U,V)UαVβ(U,V)|σ(αβ)||σ(αβ)|

Cuối cùng, bằng cách sử dụng thuật toán đường dẫn ngắn nhất của Dijkstra, chúng tôi tính toán đường đi ngắn nhất từ không đầu cuối ban đầu đến từng đầu cuối của ngữ pháp. Đưa ra đường dẫn ngắn nhất cho không đầu cuối , các nhãn quy tắc trên các cung có thể được sử dụng để lấy đạo hàm . Sau đó, theo mọi quy tắc của mẫu trong ngữ pháp, chúng tôi liên kết chuỗi thiết bị đầu cuối kích thước tối thiểu có thể được bắt nguồn bằng quy tắc đó.SUSαUβUγσ(αγβ)

Để đạt được độ phức tạp thấp , cả thuật toán của Dijkstra và phần mở rộng của Knuth đều được triển khai với hàng đống , hàng đợi ưu tiên AKA. Điều này mang lại cho thuật toán của Dijkstra độ phức tạp của và đối với thuật toán của Knuth, độ phức tạp , trong đó có quy tắc ngữ pháp và không phải là thiết bị đầu cuối và là tổng chiều dài của tất cả các quy tắc. Toàn bộ bị chi phối bởi sự phức tạp của thuật toán Knuth kể từ .O(nlogn+t)O(mlogn+t)mntmn

Những gì tiếp theo là công việc của riêng tôi, trước khi tôi đưa ra câu trả lời ngắn gọn ở trên.

Xuất phát giải pháp từ thuật toán loại bỏ biểu tượng vô dụng.

Có một số khía cạnh của thuật toán này. Để có trực giác tốt hơn, tôi đã chọn trình bày nó trong ba phiên bản liên tiếp giới thiệu nhiều tính năng hơn. Phiên bản đầu tiên không trả lời câu hỏi, nhưng là một thuật toán tiêu chuẩn để loại bỏ các biểu tượng vô dụng gợi ý một giải pháp. Phiên bản thứ hai trả lời câu hỏi mà không có ràng buộc tối thiểu, Phiên bản thứ ba đưa ra câu trả lời cho câu hỏi, thỏa mãn ràng buộc tối thiểu của bạn. Giải pháp thứ ba này sau đó được cải thiện bằng cách sử dụng một sự thích ứng với và hoặc đồ thị của thuật toán đường đi ngắn nhất của Dijkstra .

Kết quả cuối cùng là một thuật toán rất đơn giản, tránh việc xem xét lại các tính toán đã được thực hiện. Nhưng nó ít trực quan hơn và không cần bằng chứng.

Câu trả lời này chỉ cố gắng trả lời câu hỏi được đưa ra chính xác theo nhận xét của OP: " với mỗi quy tắc sản xuất, tôi muốn tạo một chuỗi tối thiểu đưa trình phân tích cú pháp từ trạng thái bắt đầu, thông qua quá trình sản xuất được kiểm tra, đến một bộ thiết bị đầu cuối. "Do đó, tôi chỉ cố gắng lấy một chuỗi các chuỗi sao cho mỗi quy tắc, có một chuỗi trong tập hợp đó là một trong các chuỗi tối thiểu kích thước của ngôn ngữ có đạo hàm sử dụng quy tắc.

Tuy nhiên, cần lưu ý rằng thực tế là một chuỗi "gọi" một quy tắc, có nguồn gốc bằng quy tắc đó, không nhất thiết có nghĩa là quy tắc này sẽ được xem xét bởi một trình phân tích cú pháp làm việc với các ngữ pháp mơ hồ và giải quyết sự mơ hồ một cách tùy tiện. Xử lý một tình huống như vậy có lẽ sẽ đòi hỏi kiến ​​thức chính xác hơn về trình phân tích cú pháp và có thể là một câu hỏi phức tạp hơn.

Thuật toán cơ bản

Để giải quyết câu hỏi này, người ta có thể bắt đầu với thuật toán cổ điển để loại bỏ các ký hiệu vô dụng trong ngữ pháp không ngữ cảnh. Nó nằm trong phần 4.4, trang 88-89, của Hopcroft & Ullman, phiên bản 1979. Nhưng cách trình bày ở đây có thể hơi khác một chút.

Thuật toán nhằm mục đích chính xác là chứng minh sự tồn tại của lớp phủ như vậy theo yêu cầu của OP và bao gồm hai phần:

  • bổ đề 4.1 của H & U, trang 88: loại bỏ tất cả các thiết bị đầu cuối không hiệu quả . Điều này được thực hiện bằng cách thử tìm cho mỗi thiết bị đầu cuối một chuỗi thiết bị đầu cuối mà nó có thể xuất phát. Một cách đơn giản để giải thích nó như sau: Bạn tạo một biểu tượng sản xuất od, mà bạn khởi tạo với tất cả các thiết bị đầu cuối. Sau đó, đối với mỗi quy tắc, chưa được xử lý, có tất cả các ký hiệu bên phải (RHS) trong , bạn thêm thiết bị đầu cuối bên trái (LHS) vào đã đặt và bạn xóa tất cả quy tắc bằng cùng một thiết bị đầu cuối LHS từ bộ quy tắc sẽ được xử lý. Bạn lặp lại quy trình cho đến khi không còn quy tắc nào với tất cả các biểu tượng RHS của nó trong . Các thiết bị đầu cuối còn lại, không có trongProdProdProdProdProdở cuối quá trình này, là không có năng suất: chúng không thể được dẫn xuất thành một chuỗi đầu cuối và do đó có thể được loại bỏ khỏi ngữ pháp.

  • bổ đề 4.2 của H & U, trang 89: loại bỏ tất cả các biểu tượng không thể truy cập . Điều này được thực hiện bởi khả năng tiếp cận nút cổ điển trong các đồ thị có hướng, bằng cách coi các thiết bị đầu cuối không phải là nút và có một cung nếu có một quy tắc sao cho xảy ra trong . Bạn có thể tạo một tập các biểu tượng có thể truy cập được khởi tạo với chỉ biểu tượng ban đầu . Sau đó, với mọi ký hiệu không đầu cuối trong hoặc sau đó được thêm vào nó và với mọi quy tắc , bạn thêm vào tất cả các ký hiệu trong(U,V)UαVαReachSUReachUαReachα. Do đó, khi tất cả các thiết bị đầu cuối trong đã được xử lý, tất cả các ký hiệu (thiết bị đầu cuối hoặc không phải thiết bị đầu cuối) không có trong không thể xuất hiện trong một chuỗi có nguồn gốc từ biểu tượng ban đầu và do đó vô dụng. Vì vậy, chúng có thể được loại bỏ khỏi ngữ pháp.ReachReach

Hai thuật toán cơ bản này rất hữu ích để đơn giản hóa kết quả thô của một số kỹ thuật xây dựng ngữ pháp, chẳng hạn như được sử dụng cho giao điểm của ngôn ngữ không ngữ cảnh và bộ thông thường. Đặc biệt, điều này rất hữu ích trong việc làm sạch kết quả của các trình phân tích cú pháp CF chung .

Loại bỏ các ký hiệu không đầu cuối vô dụng là cần thiết trong bối cảnh giải quyết câu hỏi được hỏi, vì các quy tắc sử dụng chúng không thể được gọi ra (nghĩa là được sử dụng trong dẫn xuất của nó) bởi bất kỳ chuỗi ngôn ngữ nào.

Xây dựng một chuỗi các chuỗi gọi mọi quy tắc

(Chúng tôi chưa tìm kiếm các chuỗi tối thiểu.)

Bây giờ trả lời cụ thể câu hỏi, người ta thực sự phải loại bỏ tất cả các biểu tượng vô dụng, cho dù các biểu tượng không thể truy cập hoặc các biểu tượng không đầu cuối không hiệu quả, một quy tắc vô dụng cũng có các thiết bị đầu cuối vô dụng như LHS. Chúng không có cơ hội được gọi một cách hữu ích khi phân tích chuỗi thiết bị đầu cuối (mặc dù một số có thể lãng phí thời gian xử lý của trình phân tích cú pháp khi chúng không bị xóa; cái nào có thể lãng phí thời gian phụ thuộc vào công nghệ trình phân tích cú pháp).

Bây giờ chúng tôi xem xét, đối với mỗi quy tắc (hữu ích), việc sản xuất một chuỗi đầu cuối gọi nó, tức là có thể được tạo bằng cách sử dụng quy tắc này. Đây thực chất là những gì được thực hiện bởi hai thuật toán trên, mặc dù chúng không lưu giữ thông tin, vì chúng hài lòng với việc chứng minh sự tồn tại của các chuỗi này để đảm bảo rằng các thiết bị đầu cuối không thể truy cập và có hiệu quả.

Chúng tôi sửa đổi thuật toán đầu tiên (bổ đề 4.1) bằng cách giữ với mỗi không đầu cuối trong tập một chuỗi đầu cuối mà nó xuất phát trên: . Đối với mỗi thiết bị đầu cuối, chúng tôi xác định là ánh xạ định danh. Khi được thêm vào tập vì quy tắc có tất cả các ký hiệu RHS của nó trong , sau đó chúng tôi xác định , mở rộng dưới dạng đồng cấu trên chuỗi và chúng tôi loại bỏ tất cả các , đó là tất cả các quy tắc với là LHS.UProdσ(U)Uσ(U)σUProdUγProdσ(U)=σ(γ)σUU

Chúng tôi sửa đổi thuật toán thứ hai (bổ đề 4.2) bằng cách giữ với mỗi ký hiệu không đầu cuối được thêm vào đường dẫn được sử dụng để tiếp cận nó từ ký hiệu intial , đưa ra các quy tắc liên tiếp để lấy đạo hàm .UReachSSαUβ

Sau đó, với mỗi quy tắc trong ngữ pháp, chúng tôi tạo ra một chuỗi đầu cuối "gọi" quy tắc này như sau. Chúng tôi lấy từ kết quả của thuật toán thứ hai, đạo hàm . Sau đó, chúng tôi áp dụng quy tắc để có được chuỗi . Chuỗi đầu cuối "gọi" quy tắc làUγSαUβαγβUγσ(αγβ)

Xây dựng một chuỗi các chuỗi tối thiểu "gọi" mọi quy tắc

Chúng tôi bỏ qua vấn đề loại bỏ các biểu tượng vô dụng, có thể là sản phẩm phụ của các thuật toán được sửa đổi này.

Việc xây dựng một tập hợp các chuỗi tối thiểu phụ thuộc vào việc đầu tiên nhận được một chuỗi dẫn xuất tối thiểu cho mỗi thiết bị đầu cuối. Điều này được thực hiện bằng cách sửa đổi thêm thuật toán đầu tiên (bổ đề 4.1). Trước tiên, chúng tôi xóa khỏi bộ quy tắc để được xử lý tất cả các quy tắc đệ quy (nghĩa là có ký hiệu LHS xảy ra trong chuỗi RHS). Rõ ràng là không có quy tắc nào trong số các quy tắc này có thể xuất phát từ một chuỗi thiết bị đầu cuối ngắn hơn các quy tắc không đệ quy có cùng LHS. Và phải có ít nhất một quy tắc không đệ quy nếu LHS không phải là một thiết bị đầu cuối vô dụng (vì không sản xuất).

Sau đó, chúng tôi xử lý như trước để xây dựng của các ký hiệu sản xuất, liên kết với mỗi synbol một chuỗi đầu cuối, mà chúng tôi lưu ý . Chuỗi được tạo ra như trước bằng cách áp dụng quy tắc , thay thế từng không đầu cuối xảy ra trong bằng . Cho đến nay, chỉ cần áp dụng quy tắc này cho một quy tắc với một không đầu cuối nhất định là LHS của nó, đầu tiên sẽ có tất cả các đầu cuối RHS không có đầu cuối trong ProdUσ(U)σ(U)UγVγσ(V)UProdvà sau đó bỏ qua những cái khác, bởi vì bất kỳ chuỗi dẫn xuất nào như vậy sẽ làm. Nhưng chúng tôi đang tìm kiếm một chuỗi dẫn xuất tối thiểu. Do đó, đối với không đầu cuối , điều này phải được thực hiện cho tất cả các quy tắc với là LHS. Nhưng chúng tôi chỉ giữ một chuỗi thiết bị đầu cuối , thay thế chuỗi hiện tại bằng chuỗi mới được tìm thấy, bất cứ khi nào chuỗi mới nhỏ hơn.UUσ(U)

Hơn nữa, bất cứ khi nào chuỗi được thay thế bằng một chuỗi nhỏ hơn, tất cả các quy tắc có sự xuất hiện của trong RHS đã được xử lý phải được đặt lại trong bộ quy tắc cần xử lý, vì thay đổi cho phép xuất phát RHS của họ trên một chuỗi ngắn hơn. Vì vậy, làm điều này sẽ đòi hỏi nhiều lần lặp hơn, nhưng cuối cùng sẽ kết thúc vì không có chuỗi nào trong số các chuỗi này ngắn hơn nhiều so với chuỗi trống.σ(U)U

Vào cuối của thuật toán đầu tiên này, chuỗi là một trong những chuỗi nhỏ nhất có thể được bắt nguồn từ . Có thể có người khác.σ(U)U

Bây giờ chúng ta cũng phải sửa đổi thuật toán thứ hai để có được, với mọi không đầu cuối , (một trong) chuỗi ngắn nhất chứa U là duy nhất không đầu cuối. Để làm điều này, chúng tôi giữ cùng một đồ thị có hướng với các nút không phải là các nút và có một cung nếu có quy tắc . Nhưng bây giờ chúng tôi đặt trọng số lên các cung, để tính độ dài tối thiểu của bối cảnh thiết bị đầu cuối phải được liên kết với các thiết bị đầu cuối không tiếp cận được. Trọng số liên quan đến cung ở trên là chiều dài, nơi ánh xạU(U,V)UαVβ(U,V)|σ(αβ)|σđược mở rộng đến các thiết bị đầu cuối dưới dạng danh tính, và sau đó được mở rộng lại dưới dạng đồng cấu chuỗi. Đó là độ dài của (một trong) các chuỗi đầu cuối ngắn nhất có thể được lấy từ chuỗi . Lưu ý rằng được loại bỏ trong tính toán này. HOwever, khi có một vài lần xuất hiện của trong RHS, chỉ một lần phải được loại bỏ. Có thể có một số cung , với các trọng số khác nhau, nếu có một số quy tắc với là LHS và trong RHS. Trong trường hợp như vậy, chỉ (một trong) vòng cung nhẹ hơn như vậy được giữ.αβVV(U,V)UV

Trong biểu đồ này, chúng ta không còn trông giống cho reachability các nút từ , nhưng đối với con đường ngắn nhất có trọng mà đạt mỗi nút từ biểu tượng ban đầu . Điều này có thể được thực hiện với thuật toán của Dijkstra .SS

Đưa ra con đường ngắn nhất cho một không đầu cuối , chúng ta đọc nó như trước đây như là một chuỗi các quy tắc, từ đó chúng ta nhận được một giới hạn . Sau đó, theo mọi quy tắc của mẫu trong ngữ pháp, chúng tôi tạo ra một chuỗi thiết bị đầu cuối tối thiểu "gọi" quy tắc này là USαUβUγσ(αγβ)

Lưu ý : Chuỗi tối thiểu tương tự có thể được sử dụng cho một số quy tắc. Nhưng thực tế là một trong các chuỗi sử dụng quy tắc trong đạo hàm của nó không nhất thiết có nghĩa là một chuỗi tối thiểu cho quy tắc đó , vì nó có thể được tìm thấy cho quy tắc khác, trong khi một chuỗi ngắn hơn có thể được tìm thấy cho . Có thể tăng khả năng rằng chuỗi tối thiểu tương tự sẽ được tìm thấy cho một số quy tắc bằng cách sử dụng một số chính sách ưu tiên bất cứ khi nào có tính linh hoạt. Nhưng nó có đáng để gặp rắc rối không?ρρρ

Một thuật toán nhanh hơn cho chuỗi thiết bị đầu cuối tối thiểu xuất phát từ một thiết bị đầu cuối không

Xây dựng hàm sao cho là một chuỗi đầu cuối tối thiểu xuất phát từ được thực hiện ở trên với một kỹ thuật khá ngây thơ đòi hỏi phải xem xét lại công việc đã được thực hiện khi tìm thấy một chuỗi dẫn xuất nhỏ hơn cho một số đầu cuối không. Điều này là lãng phí, ngay cả khi quá trình sẽ chấm dứt rõ ràng.σσ(U)U

Chúng tôi đề xuất ở đây một thuật toán hiệu quả hơn, về bản chất là sự thích ứng với biểu đồ ngữ pháp CF của một phần mở rộng của thuật toán đường đi ngắn nhất của Dijkstra đến và hoặc đồ thị, với một định nghĩa đúng về khái niệm đường dẫn cho một và hoặc biểu đồ . Biến thể của thuật toán này có thể tồn tại trong tài liệu (giả sử nó là chính xác), nhưng tôi đã không thể tìm thấy nó trong các tài nguyên mà tôi có thể truy cập. Do đó tôi đang mô tả nó chi tiết hơn, cùng với một bằng chứng.

Như trước đây, trước tiên chúng tôi xóa khỏi bộ quy tắc để được xử lý tất cả các quy tắc đệ quy (nghĩa là các quy tắc có ký hiệu LHS xảy ra trong chuỗi RHS). Rõ ràng là không có quy tắc đệ quy nào có thể rút ra chuỗi đầu cuối ngắn hơn quy tắc không đệ quy có cùng LHS. Và, đối với LHS , phải có ít nhất một không đệ quy nếu ký hiệu không phải là một thiết bị đầu cuối vô dụng (vì không có năng suất). Điều này không thực sự cần thiết, nhưng làm giảm số lượng các quy tắc sẽ được xem xét sau này.UUU

Sau đó, chúng tôi tiến hành xây dựng của các ký hiệu sản xuất, liên kết với mỗi synbol một chuỗi đầu cuối, mà chúng tôi lưu ý , là một chuỗi đầu cuối tối thiểu có kích thước có thể lấy được từ (trong thuật toán trước đó, chỉ đúng sau khi chấm dứt). Bộ được khởi tạo với tất cả các ký hiệu đầu cuối và với mỗi ký hiệu đầu cuối , chúng tôi xác định .ProdXσ(X)XProdaσ(a)=a

Sau đó, chúng tôi xem xét mọi quy tắc sao cho tất cả các biểu tượng RHS đều có trong và chúng tôi chọn một quy tắc sao cho có kích thước tối thiểu. Sau đó chúng ta thêm để , với , và loại bỏ tất cả -rules. Chúng tôi lặp đi lặp lại cho đến khi tất cả các thiết bị đầu cuối đã được nhập vào . Bất kỳ không đầu cuối nào , một khi đã được nhập vào , sẽ không bao giờ phải xem xét lại để thay đổi cho một chuỗi nhỏ hơn.UγProdσ(γ)UProdσ(U)=σ(γ)UProdUProdσ(U)

Bằng chứng :

Các thuật toán trước đây ít nhiều rõ ràng bằng trực giác. Đây là một chút phức tạp hơn, bởi vì và hoặc hoặc nhân vật của biểu đồ, và một bằng chứng dường như cần thiết hơn. Tất cả những gì chúng ta cần thực sự là bổ đề sau, nó thiết lập tính chính xác của thuật toán khi áp dụng cho lần lặp cuối cùng.

Bổ đề : Sau mỗi lần lặp của thuật toán, là một chuỗi đầu cuối kích thước tối thiểu có thể lấy được từ , cho tất cả trong .σ(X)XXProd

Bước cơ bản là rõ ràng, vì điều này là đúng theo định nghĩa cho tất cả các thiết bị đầu cuối trong khi nó được khởi tạo.Prod

Sau đó, giả sử đó là sự thật sau khi một số thiết bị đầu cuối không được thêm vào , hãy để là quy tắc được chọn để thêm một thiết bị đầu cuối mới vào . Chúng tôi biết rằng quy tắc này được chọn vì và có kích thước tối thiểu trên tất cả RHS của tất cả các quy tắc có RHS trong . Sau đó sẽ được thêm vào , và chúng tôi chỉ phải chứng minh rằng là một thiết bị đầu cuối chuỗi derivable size-tối thiểu từ .ProdUγProdγProdσ(γ)ProdUProdσ(γ)U

Đây rõ ràng là trường hợp của tất cả các dẫn xuất bắt đầu bằng quy tắc , vì theo giả thuyết cảm ứng, ứng dụng ánh xạ sao cho tất cả các thiết bị đầu cuối trong được thay thế bằng các chuỗi đầu cuối kích thước tối thiểu xuất phát từ chúng. Do đó không có dẫn xuất khác có thể tạo ra một chuỗi thiết bị đầu cuối ngắn hơn.Uγσσ

Do đó, chúng tôi chỉ xem xét các dẫn xuất bắt đầu bằng một -rule , sao cho , trong đó là tập hợp các ký hiệu đầu cuối.UUββwΣΣ

Nếu , thì một chuỗi tối thiểu mà nó có thể rút ra là . Nhưng, vì chúng tôi đã chọn quy tắc , nên nó phải là. Vì vậy, quy tắc không xuất phát từ một chuỗi con thiết bị đầu cuối nhỏ hơn.βProdσ(β)Uγ|σ(β)||σ(γ)|Uβ

Trường hợp cuối cùng cần xem xét là khi và sau đó chúng tôi xem xét một dẫn xuất . Nếu đạo hàm đó chỉ liên quan đến các số không phải là ba cực trong , thì , đó là trường hợp chúng ta đã thấy. Do đó, chúng tôi chỉ xem xét các dẫn xuất có các bước sử dụng quy tắc với LHS của nó không có trong . Đặt là một quy tắc, sao cho . Phải có ít nhất một quy tắc như vậy vì chúng được sắp xếp một phần theo thứ tự phái sinh và .βProdβwΣProdβProdProdVααProdwProd

Do đó, chúng ta có . Chúng tôi biết rằng và xuất phát từ một chuỗi có kích thước ít nhất là 0 và vì không có nào có RHS trong được chọn, nên chúng xuất phát từ các chuỗi đầu cuối có độ dài ít nhất bằng . Do đó, với quy tắc , xuất phát trên chuỗi đầu cuối có độ dài ít nhất bằng . UβμVνμνVProd|σ(γ)|UβU|σ(γ)|


có vẻ hợp lý nhưng đề nghị nó cần phải được chuyển đổi ít nhất thành mã giả. Ngoài ra, có vẻ hợp lý vấn đề hoặc các biến thể gần đã được nghiên cứu trong tài liệu ở đâu đó ...
vzn

@vzn Tôi nghi ngờ vấn đề này đã được xuất bản, vì tôi không thấy một ứng dụng nào yêu cầu sự tối thiểu này. Thuật toán loại bỏ các ký hiệu vô dụng là một kỹ thuật cổ điển, có thể được tìm thấy trong tất cả các sách giáo khoa về ngôn ngữ CF. Và, như tôi đã nói, nó có một số ứng dụng trong phân tích cú pháp CF nói chung. Tôi chưa bao giờ nghe về việc đẩy nó đi xa hơn để sản xuất câu kiểm tra. Tôi đã chọn thử giải thích sự phát sinh của nó, thay vì đưa ra mã giả. Vì nó là câu trả lời đã rất dài. Có thể trong câu trả lời thứ hai, nếu điều đó được chấp nhận trên trang web ... vì văn bản đang trở nên quá dài để xử lý.
babou

@vzn Điều có thể có trong tài liệu là phần mở rộng của thuật toán đường đi ngắn nhất của Dijkstra đến và hoặc đồ thị. Thật không may, tôi không có quyền truy cập vào các tài nguyên để tìm hiểu. Tôi có thể viết nó lên ở dạng đơn giản, không có các ngữ pháp CF. Nhưng sau đó, tôi không nghĩ đó là một vấn đề lớn. Nhưng nó đưa ra gợi ý đúng để thực hiện với độ phức tạp thấp.
babou

giảm thiểu & "lớp phủ" là những cân nhắc phổ biến trong tài liệu lý thuyết. nghĩ thêm, có thể một hình thức bình thường hoặc Greibach hoặc Chomsky có thể là chìa khóa để hiểu rõ hơn về nó (có một mối liên hệ nào đó với việc loại bỏ các thiết bị đầu cuối không hiệu quả / biểu tượng không thể truy cập). nghĩ rằng đây là câu hỏi đáng giá cho tcs.se, có thể hỏi nó tại một số pt ở đó & trích dẫn câu hỏi này (di chuyển afaik có xu hướng mất bình luận.)
vzn

@vzn Tôi nghi ngờ Greibach hoặc Chomsky hình thức bình thường sẽ mang lại bất kỳ ánh sáng. Đây là phụ thuộc ngữ pháp nhiều hơn phụ thuộc ngôn ngữ. Thay đổi ngữ pháp thay đổi vấn đề. Thật ra, lần đầu tiên tôi nghĩ đó là một bãi rác bài tập về nhà. Yêu cầu tối thiểu sẽ mang lại cho nó một số lợi ích, vì việc tìm kiếm một thuật toán tốt ít rõ ràng hơn, đặc biệt là phiên bản cuối cùng của tôi. Tôi đã viết bằng chứng vì tôi không thể thuyết phục bản thân bằng bất kỳ cách nào khác mà nó thực sự hoạt động. Một cách nào đó ít trực quan hơn là thuật toán của Dijkstra mà tôi bắt nguồn từ đó.
babou

2

Một giải pháp đơn giản

Nếu bạn không quan tâm quá nhiều về số lượng chuỗi, có một giải pháp dễ dàng. Về cơ bản, đối với mỗi sản xuất, chúng tôi sẽ tạo ra một chuỗi bao gồm sản xuất đó.

làm sao chúng ta làm việc đó bây giờ? Đó là một thuật toán danh sách công việc đơn giản. Giả sử chúng ta muốn bao gồm việc sản xuất . Về cơ bản, chúng tôi thực hiện tìm kiếm theo chiều rộng đầu tiên bắt đầu từ đầu không phải đầu cuối để tìm một đạo hàm bao gồm đầu cuối ở phía bên phải: ban đầu, tất cả các đầu cuối không được đánh dấu và tập hợp các đầu cuối không tiếp cận được là ; trong mỗi lần lặp, chúng tôi chọn một thiết bị đầu cuối không thể truy cập không đánh dấu, giả sử và với mỗi sản xuất với ở phía bên trái, chúng tôi thêm tất cả các thiết bị đầu cuối bên phải vào bộ thiết bị đầu cuối có thể tiếp cận, sau đó chúng tôi đánh dấu . Lặp lại cho đến khi quá trình này thấy rằngA::=BCxSA{S}XXXAcó thể truy cập. Khi đó, bằng cách backtracing, bạn có được một dẫn xuất của mẫu . Bạn có thể mở rộng điều này thành một dẫn xuất của mẫu .SASABCx

Tiếp theo, chúng ta cần hoàn thành đạo hàm, bằng cách chọn một số cách để hoàn thành nó là tất cả các thiết bị đầu cuối. Điều này cũng dễ dàng. Đối với mỗi phi đầu cuối, chúng tôi tìm thấy chuỗi ngắn nhất trong ngôn ngữ được tạo bởi các đầu cuối đó. Điều này có thể thu được bằng cách lặp lại danh sách công việc. Hãy biểu thị độ dài của chuỗi ngắn nhất chúng tôi đã tìm thấy cho đến nay trong các ngôn ngữ được tạo ra bởi . Ban đầu, chúng tôi đặt cho tất cả các thiết bị đầu cuối , trừ khi có sản phẩm trong đó tất cả các biểu tượng ở phía bên phải là thiết bị đầu cuối; trong trường hợp đó, chúng tôi đặt tương ứng (ví dụ: nếu việc sản xuất cho chúng tôi biết rằng(A)A(A)=AA::=xyz(A)(A)=3xyznằm trong ). Bây giờ chúng tôi lặp đi lặp lại tìm cách để tìm một chuỗi ngắn hơn. Nếu bạn có một sản phẩm như , bạn biết rằng ; vì vậy bất cứ khi nào bạn tìm thấy một chuỗi ngắn mới trong hoặc (tức là bất cứ khi nào bạn cập nhật hoặc nhỏ hơn), bạn có thể kiểm tra xem điều này có mang lại cho bạn không chuỗi ngắn mới trong và nếu vậy, hãy giảm giá trị củaL(A)A::=xBCy(A)2+(B)+(C)L(B)L(C)(B)(C)L(A)(A)... Điều này có thể lần lượt gây ra thay đổi tầng khác. Tiếp tục áp dụng tất cả các thay đổi xếp tầng cho đến khi không có thay đổi nào được kích hoạt. Tại thời điểm đó, bạn đã đạt đến một điểm cố định và bằng cách backtracing, đối với mỗi thiết bị không đầu cuối, bạn biết chuỗi ngắn nhất (của thiết bị đầu cuối) có thể được lấy từ thiết bị đầu cuối đó.

Bây giờ, với đạo hàm của bạn có dạng , hãy tìm cách hoàn thành đạo hàm: thay thế mỗi đầu cuối trong bằng chuỗi ngắn nhất (của thiết bị đầu cuối) có thể được lấy từ nó .SBCxBCx

Điều này cung cấp cho bạn một chuỗi (của các thiết bị đầu cuối) bao gồm việc sản xuất . Làm điều này một lần cho mỗi sản xuất, cho đến khi tất cả chúng được bảo hiểm.A::=BCx

Số lượng chuỗi bằng số lượng sản phẩm. Thời gian chạy là bậc hai: quá trình là thời gian tuyến tính cho mỗi sản xuất. (Bạn có thể có thể giảm nó thành một thuật toán thời gian tuyến tính, nhưng tôi nghi ngờ điều này sẽ đủ tốt trong thực tế.)

Tối ưu hóa

Nếu bạn muốn giảm số lượng chuỗi, bạn có thể nhận thấy rằng mỗi chuỗi thường sẽ bao gồm nhiều sản phẩm, do đó, một tập hợp con của các chuỗi này có thể sẽ đủ.

Có nhiều cách bạn có thể giảm số lượng chuỗi. Một cách đơn giản là sử dụng thuật toán xấp xỉ tham lam tiêu chuẩn cho trang bìa. Bắt đầu bằng cách tạo tất cả các chuỗi như trên, một chuỗi cho mỗi sản xuất và tính xem có bao nhiêu sản phẩm mỗi chuỗi. Giữ chuỗi bao gồm hầu hết các sản phẩm; cái mà bạn chắc chắn muốn, vì vậy hãy thêm nó vào bộ giữ của bạn. Bây giờ một số sản phẩm được bảo vệ bởi người quản lý này, vì vậy chúng tôi không cần bất kỳ chuỗi mới nào bao phủ chúng một lần nữa. Vì vậy, bạn nên cập nhật bộ số đếm của mình cho từng chuỗi: đối với chuỗi , hãy đếm số lượng sản phẩm được bao phủ bởissnhưng không được bảo vệ bởi bất kỳ người quản lý. Chọn chuỗi có số lớn nhất, thêm chuỗi vào bộ giữ của bạn và cập nhật lại số đếm. Lặp lại cho đến khi tất cả các sản phẩm đã được bảo hiểm. Điều này có thể sẽ cung cấp cho bạn một chuỗi các chuỗi nhỏ hơn đáng kể bao gồm tất cả các sản phẩm trong ngữ pháp của bạn.

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.