Một ngôn ngữ giống như chữ C nhỏ mà máy turing có thể mô phỏng


11

Tôi đang tìm kiếm một ngôn ngữ nhỏ giúp 'thuyết phục' sinh viên rằng máy turing là một mô hình điện toán đủ chung. Đó là, một ngôn ngữ trông giống như ngôn ngữ mà họ đã quen, nhưng cũng dễ dàng mô phỏng trên một máy turing.

Papadimitriou sử dụng máy RAM cho công việc này, nhưng tôi sợ rằng việc so sánh thứ gì đó kỳ lạ (như một máy turing) với một thứ lạ khác (về cơ bản, một ngôn ngữ lắp ráp) sẽ quá thiếu thuyết phục đối với nhiều sinh viên.

Bất kỳ đề xuất nào sẽ được hoan nghênh nhất (đặc biệt nếu chúng đi kèm với một số tài liệu được đề xuất)


7
Có một lý do mà các máy tính ban đầu được lập trình bằng ngôn ngữ lắp ráp ... viết trình biên dịch hoặc trình thông dịch không phảichuyện nhỏ . Và viết trình biên dịch hoặc thông dịch viên cho máy Turing có lẽ còn khó hơn.
Peter Shor

phải không đồng ý với PS, trình biên dịch TM không khó hơn nhiều so với việc chuyển đổi các trường hợp bao thanh toán sang SAT hoặc các bài tập gần đại học khác. xem thêm mô phỏng máy turing hàng đầu trên web . đây là một ví dụ về trình biên dịch máy Turing được viết bằng ruby ​​với mã nguồn mẫu (đối với ngôn ngữ cấp cao). than ôi dường như không có nhiều đánh bóng có sẵn. nó sẽ làm cho một dự án nguồn mở tuyệt vời.
vzn

2
@OmarShehab, Một chỉnh sửa sẽ đưa câu hỏi lên trang đầu tiên. Vui lòng không chỉnh sửa câu hỏi cũ khi chỉnh sửa không cải thiện đáng kể câu hỏi. Ngoài ra, việc chỉnh sửa một số lượng lớn câu hỏi không có trên trang đầu tiên là không tốt vì nó đẩy các câu hỏi mới ra khỏi trang đầu tiên. Cảm ơn.
Kaveh

@kaveh hiểu.
Omar Shehab

Câu trả lời:


15
  • smnutm

    Tôi nghi ngờ đây là cách tiếp cận đơn giản nhất có thể, nhưng tôi thích cách nó dựa trên một số định lý cơ bản nhất về khả năng tính toán (mà bạn có thể muốn đưa ra vì những lý do khác).

    Có vẻ như Andrej Bauer đã trả lời một câu hỏi tương tự trên Mathoverflow vài tháng trước.

  • Nếu bạn được đặt trên một ngôn ngữ giống như C, con đường của bạn sẽ khó khăn hơn rất nhiều, vì chúng có ngữ nghĩa khá phức tạp - bạn sẽ cần phải

    1. Cho thấy rằng các máy Turing có thể mô phỏng một chồng và một đống cùng một lúc, và
    2. Chỉ ra cách các biến có thể được thực hiện với một ngăn xếp và
    3. Chỉ ra rằng các cuộc gọi thủ tục có thể được thực hiện với một ngăn xếp.

    Đây là phần lớn nội dung của một lớp trình biên dịch, trung thực.


7

Lý thuyết của tôi về giáo sư Comp ở đại học bắt đầu bằng cách chứng minh rằng một máy Turing băng đơn có thể thực hiện một máy Turing nhiều băng. Điều này xử lý khai báo biến: nếu một chương trình có sáu khai báo biến, thì có thể dễ dàng thực hiện trên máy Turing bảy băng (một băng cho mỗi biến và băng "đăng ký" để giúp thực hiện các nhiệm vụ như kiểm tra số học và kiểm tra đẳng thức giữa băng). Sau đó, ông chỉ ra cách thực hiện các vòng lặp FOR và WHILE cơ bản, và tại thời điểm đó, chúng tôi đã có một ngôn ngữ giống như C hoàn chỉnh Turing cơ bản. Tôi thấy nó thỏa mãn, dù sao đi nữa.


6

Tôi đang suy nghĩ về cách thuyết phục bản thân rằng máy Turing là một mô hình tính toán chung. Tôi đồng ý rằng cách xử lý tiêu chuẩn của luận án Church-Turing trong một số sách giáo khoa tiêu chuẩn, ví dụ Sipser, là không đầy đủ. Dưới đây là một bản phác thảo về cách tôi có thể đi từ máy Turing sang ngôn ngữ lập trình dễ nhận biết hơn.

Hãy xem xét một ngôn ngữ lập trình có cấu trúc khối với ifvà các whilecâu lệnh, với các hàm và chương trình con được xác định không đệ quy , với các biến ngẫu nhiên boolean được đặt tên và các biểu thức boolean chung, và với một mảng boolean không liên kết duy nhất tape[n]với một con trỏ mảng số nguyên ncó thể tăng hoặc giảm, n++hoặc n--. Con trỏ nban đầu bằng không và mảng tapeban đầu đều bằng không. Vì vậy, ngôn ngữ máy tính này có thể giống như C hoặc Python, nhưng nó rất hạn chế trong các loại dữ liệu của nó. Trên thực tế, chúng bị giới hạn đến mức chúng ta thậm chí không có cách nào để sử dụng con trỏ ntrong biểu thức boolean. Giả sử rằngtapechỉ vô hạn ở bên phải, chúng ta có thể khai báo một con trỏ dưới "lỗi hệ thống" nếu nlà âm. Ngoài ra, ngôn ngữ của chúng tôi có một exitcâu lệnh với một đối số, để đưa ra câu trả lời boolean.

Sau đó, điểm đầu tiên là ngôn ngữ lập trình này là ngôn ngữ đặc tả tốt cho máy Turing. Bạn có thể dễ dàng thấy rằng, ngoại trừ mảng băng, mã chỉ có nhiều trạng thái có thể có: Trạng thái của tất cả các biến được khai báo và dòng thực thi hiện tại và ngăn xếp chương trình con của nó. Cái sau chỉ có một lượng trạng thái hữu hạn vì các hàm đệ quy không được phép. Bạn có thể tưởng tượng một "trình biên dịch" tạo ra một máy Turing "thực tế" từ một mã thuộc loại này, nhưng các chi tiết về điều đó không quan trọng. Vấn đề là chúng ta có một ngôn ngữ lập trình với cú pháp khá tốt, nhưng các kiểu dữ liệu rất nguyên thủy.

Phần còn lại của quá trình xây dựng là chuyển đổi ngôn ngữ này thành ngôn ngữ lập trình dễ sống hơn với danh sách hữu hạn các chức năng thư viện và các giai đoạn tiền biên dịch. Chúng tôi có thể tiến hành như sau:

  1. Với trình biên dịch trước, chúng ta có thể mở rộng kiểu dữ liệu boolean thành bảng chữ cái ký hiệu lớn hơn nhưng hữu hạn như ASCII. Chúng ta có thể giả định rằng tapecó các giá trị trong bảng chữ cái lớn hơn này. Chúng ta có thể để lại một điểm đánh dấu ở đầu băng để ngăn dòng chảy con trỏ và một điểm đánh dấu có thể di chuyển ở cuối băng để ngăn TM vô tình trượt đến vô cực trên băng. Chúng ta có thể thực hiện các hoạt động nhị phân tùy ý giữa các ký hiệu và chuyển đổi sang boolean cho ifvà các whilecâu lệnh. (Trên thực tế ifcũng có thể được thực hiện whilenếu không có sẵn.)

  2. kkiik

  3. Chúng tôi chỉ định một băng là "bộ nhớ" có giá trị ký hiệu và các băng khác là "các thanh ghi" hoặc "biến" có giá trị nguyên. Chúng tôi lưu trữ các số nguyên trong nhị phân nhỏ cuối cùng với các dấu chấm dứt. Trước tiên chúng tôi thực hiện bản sao của một thanh ghi và giảm nhị phân của một thanh ghi. Kết hợp điều đó với sự tăng giảm của con trỏ bộ nhớ, chúng ta có thể thực hiện tìm kiếm truy cập ngẫu nhiên của bộ nhớ ký hiệu. Chúng ta cũng có thể viết các hàm để tính toán cộng và nhân số nguyên. Không khó để viết một hàm cộng nhị phân với các phép toán bitwise và hàm nhân 2 với dịch chuyển trái. (Hoặc thay đổi thực sự đúng, vì nó là endian nhỏ.) Với các nguyên hàm này, chúng ta có thể viết một hàm để nhân hai thanh ghi bằng thuật toán nhân dài.

  4. Chúng ta có thể sắp xếp lại băng nhớ từ mảng ký hiệu symbol[n]một chiều thành mảng ký hiệu hai chiều symbol[x,y]bằng công thức n = (x+y)*(x+y) + y. Bây giờ chúng ta có thể sử dụng mỗi hàng của bộ nhớ để thể hiện một số nguyên không dấu trong hệ nhị phân với ký hiệu kết thúc, để có được bộ nhớ có giá trị một chiều, truy cập ngẫu nhiên, có giá trị nguyên memory[x]. Chúng ta có thể thực hiện đọc từ bộ nhớ đến một thanh ghi số nguyên và ghi từ một thanh ghi vào bộ nhớ. Nhiều tính năng hiện có thể được thực hiện với các chức năng: Số học đã ký và dấu phẩy động, chuỗi ký hiệu, v.v.

  5. Chỉ có một cơ sở cơ bản hơn yêu cầu nghiêm ngặt một bộ biên dịch trước, cụ thể là các hàm đệ quy. Điều này có thể được thực hiện với một kỹ thuật được sử dụng rộng rãi để thực hiện các ngôn ngữ được dịch. Chúng tôi gán cho mỗi hàm cấp cao, hàm đệ quy một chuỗi tên và chúng tôi sắp xếp mã cấp thấp thành một whilevòng lặp lớn duy trì một ngăn xếp cuộc gọi với các tham số thông thường: điểm gọi, hàm được gọi và danh sách các đối số.

Tại thời điểm này, việc xây dựng có đủ các tính năng của ngôn ngữ lập trình cấp cao mà chức năng tiếp theo là chủ đề của ngôn ngữ lập trình và trình biên dịch hơn là lý thuyết CS. Thật dễ dàng để viết một trình giả lập Turing-machine bằng ngôn ngữ phát triển này. Nó không chính xác dễ dàng, nhưng chắc chắn là tiêu chuẩn, để viết một trình biên dịch tự cho ngôn ngữ. Tất nhiên bạn cần một trình biên dịch bên ngoài để tạo TM bên ngoài từ một mã trong ngôn ngữ giống như C hoặc Python này, nhưng điều đó có thể được thực hiện bằng bất kỳ ngôn ngữ máy tính nào.

Lưu ý rằng việc triển khai phác thảo này không chỉ hỗ trợ cho luận điểm Church-Turing của các nhà logic cho lớp chức năng đệ quy, mà còn cả luận điểm Church-Turing mở rộng (nghĩa là đa thức) khi áp dụng cho tính toán xác định. Nói cách khác, nó có chi phí đa thức. Trên thực tế, nếu chúng ta được tặng một máy RAM hoặc (sở thích cá nhân của tôi) một TM băng cây, điều này có thể được giảm xuống trên tổng thể polylogarithmic để tính toán nối tiếp với bộ nhớ RAM.


5

Trình biên dịch LLVM cho phép một người khá đơn giản "cắm" một kiến ​​trúc mới. Họ gọi bài viết này là một back-end mới , và đưa ra các hướng dẫn và ví dụ chi tiết về cách thực hiện nó. Tôi nghi ngờ rằng bạn sẽ phải nhảy qua một số vòng liên quan đến bộ nhớ truy cập ngẫu nhiên, nếu bạn không muốn nhắm mục tiêu máy RAM Turing, nhưng điều này chắc chắn là có thể, vì tôi đã thấy một số dự án khiến LLVM tạo ra VHDL hoặc các ngôn ngữ máy rất khác nhau.

Điều này sẽ có tác dụng thú vị khi có một trình biên dịch tối ưu hóa hiện đại (theo nhiều cách LLVM tiên tiến hơn GCC) tạo mã cho máy Turing.


1

Tôi không theo lý thuyết cs nhưng đôi khi tôi có thể hữu ích. Tôi đã thực hiện một phê duyệt khác. Tôi đã thiết kế một bộ xử lý đơn giản có thể lập trình trực tiếp với một tập hợp con nhỏ C. KHÔNG có mã lắp ráp, chỉ có mã giống như C. Bạn có thể sử dụng cùng một công cụ tôi đã sử dụng và sửa đổi bộ xử lý này để thiết kế trình giả lập máy Turing của bạn. Tôi mất 4 ngày để thiết kế, mô phỏng và thử nghiệm bộ xử lý này, một vài hướng dẫn! Các công cụ tôi đã sử dụng thậm chí cho phép tôi tạo mã tổng hợp VHDL thực. Nó là một bộ xử lý làm việc thực sự.

Đây là những gì một chương trình trông giống như: Ví dụ về chương trình hội C-Like

Dưới đây là hình ảnh của bộ xử lý sử dụng các công cụ này. Mạch xử lý

Công cụ "Novakod Studio" sử dụng Ngôn ngữ mô tả phần cứng ngôn ngữ cấp cao. Ví dụ, đây là mã của bộ đếm chương trình: psC - Mẫu mã C song song và đồng bộ Nói đủ rồi, nếu có ai quan tâm, đây là thông tin công khai để liên hệ với tôi: https://repertoire.uqac.ca/Fiche.aspx?id=JjstNzsH0&link=1

Lục


địa chỉ bộ nhớ có sử dụng số bit cố định để định vị địa chỉ không?
vzn

Có, nhưng thật đơn giản để thay đổi kích thước bộ nhớ (int DataMemory [SIZE]. Ngôn ngữ hỗ trợ số nguyên có độ dài thay đổi (int: 10). Nhưng, vì nó nhắm vào FPGA, mảng là hằng số tĩnh và kích thước.
Luc Morin

1

Làm thế nào về việc lấy ý tưởng được đại diện bởi người dùng GMB ở đây (Máy Turing với một băng có thể mô phỏng máy Turing với băng N bằng cách xen kẽ các băng N vào một băng và đọc bất kỳ một trong các băng đó bằng cách nhảy N vị trí cùng một lúc, Turing máy có băng N có thể thực hiện ...) và viết chương trình máy Turing thực hiện máy RAM đơn giản. Máy RAM thực sự có thể là một số CPU đơn giản, thực, với phần phụ trợ LLVM hoặc GCC có sẵn. Sau đó, GCC / LLVM có thể được sử dụng để biên dịch chéo chương trình C cho CPU đó và chương trình máy Turing mô phỏng máy RAM, chạy mô phỏng máy RAM bằng cách cho máy RAM mô phỏng thực hiện đầu ra GCC / LLVM. Việc triển khai máy Turing có thể là một số mã C rất đơn giản phù hợp với một tệp C nhỏ.

Liên quan đến máy RAM, sau đó tồn tại một dự án demo, trong đó CPU 32 bit được mô phỏng bởi vi điều khiển 8 bit và CPU 32 bit mô phỏng khởi động Linux. Chậm như địa ngục, nhưng theo tác giả , Dmitry Grinberg, nó đã hoạt động. Có lẽ CPU Zylin (zitin người dùng GitHub) có thể là một lựa chọn khả thi cho máy RAM có thể mô phỏng . Một ứng cử viên máy RAARK khác có thể là ProjectOberon dot com của Niklaus Wirth .

. rằng họ có thể tự động nhìn thấy từ các tài khoản stackexchange khác của tôi rằng tôi có thể ngu ngốc, nhưng tôi không phải là một kẻ troll.)

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.