Một môi trường thời gian chạy có thể phát hiện một vòng lặp vô hạn?


19

Liệu một môi trường thời gian chạy có thể phát hiện các vòng lặp vô hạn và sau đó dừng quá trình liên quan, hoặc thực hiện logic như vậy sẽ tương đương với việc giải quyết vấn đề tạm dừng?

Với mục đích của câu hỏi này, tôi định nghĩa một "vòng lặp vô hạn" có nghĩa là một chuỗi các hướng dẫn và dữ liệu stack / heap bắt đầu, khi được thực thi, trả lại quá trình về chính xác trạng thái (bao gồm cả dữ liệu) như trước đây khởi đầu vòng lặp vô hạn. (Nói cách khác, một chương trình tạo ra sự mở rộng thập phân dài vô hạn của pi không bị "kẹt" trong một "vòng lặp vô hạn", bởi vì ở mỗi lần lặp, nó có nhiều chữ số pi ở đâu đó trong bộ nhớ liên kết của nó.)

(Được chuyển từ /programming//q/16250472/1858225 )



Tôi không nghĩ vậy; không có ràng buộc về đầu vào.
Kyle Strand

Là câu hỏi của bạn về một môi trường thời gian chạy thực (như JVM), hoặc về một cách chung chung theo chương trình để phát hiện một vòng lặp như vậy?
13 giờ 44 phút

@Benj stackoverflow.com/q/16249785/1858225 Câu hỏi ban đầu (không phải của tôi) là về môi trường thời gian chạy thực (hay đúng hơn là về hệ điều hành). Điều đó đã bị đóng cửa, mặc dù vậy, vì vậy tôi đã viết lại nó, tôi chuyển trọng tâm sang khía cạnh lý thuyết.
Kyle Strand

ĐỒNG Ý. Cách duy nhất tôi thấy là lấy mẫu một số điểm chính và tạo hàm băm của chúng (đây có thể là dòng cuối cùng của đầu ra nhật ký hoặc một số trạng thái CPU như stack ptr) và lưu trữ băm của một bộ đầu dò (một bộ tại một thời điểm nhất định) trong Chuỗi Markov. Sau đó, bạn sẽ có thể (bằng cách chọn đúng "đầu dò") để phát hiện các khóa tuần hoàn. Tôi cũng đang suy nghĩ về việc truy cập các thư viện hệ thống truy cập và sử dụng các mục nhập của họ làm đầu dò. Thưởng thức;)
Hết

Câu trả lời:


11

Về mặt lý thuyết, môi trường thời gian chạy có thể kiểm tra các vòng lặp như vậy bằng cách sử dụng quy trình sau:

Sau khi thực hiện lệnh, môi trường thời gian chạy sẽ tạo một hình ảnh hoàn chỉnh về trạng thái của một tiến trình đang chạy (tức là tất cả bộ nhớ được liên kết với nó, bao gồm các thanh ghi, PC, stack, heap và toàn cầu), lưu hình ảnh đó vào đâu đó, rồi kiểm tra xem liệu nó phù hợp với bất kỳ hình ảnh được lưu trước đó cho quá trình đó. Nếu có một trận đấu, thì quá trình bị kẹt trong một vòng lặp vô hạn. Mặt khác, lệnh tiếp theo được thực thi và quá trình được lặp lại.

Trong thực tế, thay vì thực hiện kiểm tra này sau mỗi lệnh đơn lẻ, môi trường thời gian chạy có thể chỉ cần tạm dừng quá trình theo định kỳ và tạo trạng thái lưu. Nếu quá trình bị kẹt trong một vòng lặp vô hạn liên quan đến n trạng thái, thì sau khi nhiều nhất n kiểm tra, một trạng thái trùng lặp sẽ được quan sát.

Tất nhiên, lưu ý rằng đây không phải là một giải pháp cho vấn đề tạm dừng; sự phân biệt được thảo luận ở đây .

Nhưng một tính năng như vậy sẽ là một sự lãng phí tài nguyên to lớn ; liên tục tạm dừng một quá trình để lưu tất cả bộ nhớ liên quan đến nó sẽ làm chậm rất nhiều và tiêu tốn một lượng lớn bộ nhớ rất nhanh. (Mặc dù sau một thời gian, hình ảnh cũ có thể bị xóa, nhưng sẽ rất rủi ro khi giới hạn tổng số hình ảnh có thể được lưu vì một vòng lặp vô hạn lớn - tức là một hình ảnh có nhiều trạng thái - có thể không bị bắt nếu có quá ít trạng thái được giữ trong bộ nhớ.) Hơn nữa, tính năng này thực sự sẽ không mang lại nhiều lợi ích như vậy, vì khả năng bắt lỗi của nó sẽ vô cùng hạn chế và vì việc tìm các vòng lặp vô hạn bằng các phương pháp gỡ lỗi khác (chẳng hạn như chỉ đơn giản là bước qua mã và nhận ra lỗi logic).

Do đó, tôi nghi ngờ rằng một môi trường thời gian chạy như vậy tồn tại hoặc nó sẽ tồn tại, trừ khi có ai đó lập trình nó chỉ để đá. (Điều mà bây giờ tôi hơi bị cám dỗ để làm.)


8
Có thể (ít nhất là trong thế giới lý tưởng hóa của Turing Machines và như vậy) rằng một chương trình đi vào một vòng lặp vô hạn mà không lặp lại trạng thái . Hãy nghĩ về một cái gì đó giống như vòng lặp Cfor(i = 0; ; i++) ;
vonbrand

nn<nn+1

@vonbrand, vòng lặp cụ thể đó không phù hợp với định nghĩa của tôi về "vòng lặp" cho mục đích của câu hỏi cụ thể này (đó là lý do tại sao tôi đưa ra định nghĩa rõ ràng trong chính câu hỏi).
Kyle Strand

n

Có lẽ tôi đã không hiểu câu hỏi của bạn. Tôi nghĩ rằng bạn muốn biết liệu có thể quyết định liệu chương trình nào lặp lại trạng thái hay không. Có phải bạn chỉ hỏi liệu có thể quyết định liệu một số chương trình có lặp lại trạng thái không?
Huck Bennett

6

Giả sử rằng chương trình không tương tác với thế giới bên ngoài, vì vậy điều đó thực sự có thể gói gọn toàn bộ trạng thái của chương trình. (Điều này có nghĩa là ít nhất nó không thực hiện bất kỳ đầu vào nào.) có thể được xác định giảm xuống một chuỗi.

Theo các giả định rất khó khả thi nhưng về mặt lý thuyết, chúng tôi có thể sao chép chương trình và chạy nó trong hai thời gian chạy riêng biệt; mỗi người sẽ làm chính xác cùng một tính toán.

Vì vậy, hãy làm điều đó. Chúng tôi sẽ chạy nó một lần trong thời gian chạy Rùa và đồng thời chúng tôi sẽ chạy nó trong thời gian chạy Hare. Tuy nhiên, chúng tôi sẽ sắp xếp để thời gian chạy Hare hoạt động chính xác nhanh gấp đôi; mỗi khi thời gian chạy Rùa thực hiện một bước, thời gian chạy Hare thực hiện hai bước.

npknkknp

Tổng chi phí của bài kiểm tra là một trạng thái bổ sung và một so sánh trạng thái cho mỗi bước và nó sẽ chấm dứt không quá ba lần số bước cần thiết để chương trình hoàn thành vòng lặp đầu tiên. (Một lần trong Rùa và hai lần trong Hare, tổng cộng ba lần.)

Như các thuật ngữ tôi đã sử dụng ngụ ý, đây chỉ là thuật toán phát hiện chu kỳ Rùa và thỏ nổi tiếng của Robert Floyd .


3

Ngay khi tôi định đề xuất thuật toán phát hiện chu kỳ của Floyd, bài đăng của tôi đã đánh bại tôi. Tuy nhiên, toàn bộ điều có thể được thực hiện nhiều hơn bằng cách tăng tốc so sánh các trạng thái đầy đủ.

Nút thắt của thuật toán đề xuất sẽ là so sánh trạng thái đầy đủ. Những so sánh này thường sẽ không kết thúc, nhưng dừng lại sớm --- ở sự khác biệt đầu tiên. Một tối ưu hóa là ghi nhớ nơi xảy ra sự khác biệt trong quá khứ và kiểm tra các phần đó của trạng thái trước. Ví dụ: duy trì một danh sách các địa điểm và đi qua danh sách này trước khi so sánh đầy đủ. Khi một vị trí trong danh sách này lộ ra sự khác biệt, hãy dừng so sánh (với thất bại) và di chuyển vị trí đó lên phía trước danh sách.

Một cách tiếp cận khác (và có khả năng mở rộng hơn) là sử dụng băm tăng dần. Chọn một hàm của trạng thái đầy đủ sao cho các giá trị băm dễ điều chỉnh trong O (1) khi một phần của trạng thái thay đổi. Ví dụ: lấy một tổng số trọng số của các từ trạng thái mod một số nguyên tố lớn và ghép với một tổng số không trọng số một số nguyên tố lớn khác (cũng có thể ném vào một tổng số bình phương có trọng số mô đun, với trọng số và mô đun khác nhau). Bằng cách này, các cập nhật băm sẽ mất O (1) thời gian cho mỗi bước thực hiện và so sánh sẽ mất thời gian O (1) cho đến khi bạn nhận được một cú đánh. Xác suất dương tính giả (nghĩa là băm khớp trong khi các trạng thái khác nhau) là rất thấp và ngay cả khi điều này xảy ra, nó sẽ được khấu hao theo một số lượng lớn âm tính thực (không thể phủ định sai).

Tất nhiên, trong thực tế, dường như có nhiều khả năng gặp phải các tình huống như tạo ra các chữ số của số pi --- mọi thứ cứ thay đổi, nhưng không bao giờ kết thúc. Một khả năng thường xuyên khác là vòng lặp vô hạn phân bổ bộ nhớ, trong trường hợp đó, nó nhanh chóng cạn kiệt tất cả bộ nhớ có sẵn.

Trong khóa học của tôi về các thuật toán và cấu trúc dữ liệu, trình tự động của chúng tôi phải xử lý các bài nộp của sinh viên đôi khi rơi vào các vòng lặp vô hạn. Việc này được xử lý trong khoảng thời gian chờ 30 giây và giới hạn bộ nhớ nhất định. Cả hai đều lỏng lẻo hơn nhiều so với ngân sách thời gian chạy và bộ nhớ mà chúng ta coi là một phần của việc chấm điểm. Tôi không chắc việc triển khai phát hiện vòng lặp vô hạn thực sự có ý nghĩa gì trong bối cảnh này hay không bởi vì các chương trình như vậy sẽ chạy chậm hơn một chút (đây là lúc hỗ trợ phần cứng cho băm trạng thái có thể giúp ích, nhưng một lần nữa bạn cần sử dụng thêm để biện minh cho điều này). Khi sinh viên biết rằng chương trình của họ đã hết thời gian, họ thường có thể tìm thấy vòng lặp vô hạn.


2

Công cụ chấm dứt AProVE thực hiện phân tích tĩnh trên các hệ thống viết lại (bao gồm một lớp con của các chương trình Haskell) có thể chứng minh không kết thúc, đưa ra một ví dụ thực tế về chương trình không kết thúc. Kỹ thuật này khá mạnh mẽ và hoạt động bằng cách sử dụng một biến thể của một kỹ thuật gọi là thu hẹp .

Theo như tôi biết, không có nhiều công việc phát hiện việc không chấm dứt thực sự đối với các ngôn ngữ nói chung.

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.