Bahasa mirip-C kecil yang dapat disimulasikan oleh mesin turing

11

Saya mencari bahasa kecil yang membantu 'meyakinkan' siswa bahwa mesin turing adalah model komputasi yang cukup umum. Yaitu, bahasa yang mirip dengan bahasa yang biasa mereka gunakan, tetapi juga mudah untuk disimulasikan pada mesin turing.

Papadimitriou menggunakan mesin RAM untuk pekerjaan ini, tapi saya takut membandingkan sesuatu yang aneh (sebagai mesin turing) dengan hal aneh lainnya (pada dasarnya, bahasa assembly) akan terlalu tidak meyakinkan bagi banyak siswa.

Setiap saran akan sangat disambut (khususnya jika mereka datang dengan beberapa literatur yang direkomendasikan)

josinalvo
sumber
7
Ada alasan mengapa komputer awalnya diprogram dalam bahasa assembly ... menulis kompiler atau juru bahasa bukanlah hal sepele . Dan menulis kompiler atau juru bahasa untuk mesin Turing mungkin bahkan lebih sulit.
Peter Shor
Harus agak tidak setuju dengan PS, sebuah kompiler TM tidak jauh lebih sulit daripada misalnya mengubah contoh anjak menjadi SAT atau latihan hampir-sarjana lainnya. lihat juga simulator mesin turing teratas di web . di sini adalah contoh dari kompiler mesin Turing ditulis dalam ruby ​​dengan kode sumber sampel (untuk bahasa tingkat tinggi). Sayangnya ada tampaknya tidak lebih banyak yang dipoles tersedia. itu akan menjadi proyek open source yang hebat.
vzn
2
@OmarShehab, hasil edit memompa pertanyaan ke halaman pertama. Harap jangan edit pertanyaan lama ketika hasil edit tidak meningkatkan pertanyaan secara signifikan. Juga mengedit sejumlah besar pertanyaan yang tidak ada di halaman pertama tidak baik karena mendorong pertanyaan baru keluar dari halaman pertama. Terima kasih.
Kaveh
@kaveh mengerti.
Omar Shehab

Jawaban:

15
  • Jika siswa Anda telah melakukan pemrograman fungsional apa pun, pendekatan terbaik yang saya tahu adalah memulai dengan kalkulus lambda yang tidak diketik, dan kemudian menggunakan teorema abstraksi braket untuk menerjemahkannya ke dalam combinator SKI. Kemudian, Anda dapat menggunakan teorema dan u t m untuk menunjukkan bahwa mesin Turing membentuk aljabar kombinasi parsial , dan dengan demikian dapat menafsirkan kombinator SKI.smnkamutm

    Saya ragu ini adalah pendekatan paling sederhana yang mungkin, tapi saya suka bagaimana itu bertumpu pada beberapa teorema paling mendasar dalam komputabilitas (yang mungkin ingin Anda bahas karena alasan lain).

    Tampaknya Andrej Bauer menjawab pertanyaan serupa tentang Mathoverflow beberapa bulan yang lalu.

  • Jika Anda menggunakan bahasa C-like, jalur Anda akan jauh lebih kasar, karena mereka memiliki semantik yang agak rumit - Anda harus

    1. Tunjukkan bahwa mesin Turing dapat mensimulasikan tumpukan dan tumpukan secara bersamaan, dan
    2. Tunjukkan bagaimana variabel dapat diimplementasikan dengan tumpukan, dan
    3. Tunjukkan bahwa prosedur panggilan dapat diimplementasikan dengan tumpukan.

    Ini banyak isi dari kelas kompiler, jujur.

Neel Krishnaswami
sumber
7

Profesor Theory of Comp saya di undergrad mulai dengan membuktikan bahwa mesin Turing single-tape dapat menerapkan mesin Turing multi-tape. Ini menangani deklarasi variabel: jika suatu program memiliki enam deklarasi variabel, maka itu dapat dengan mudah diimplementasikan pada mesin Turing tujuh-tape (sebuah tape untuk setiap variabel, dan sebuah tape "register" untuk membantu melakukan tugas-tugas seperti aritmatika dan pengecekan kesetaraan antara kaset). Dia kemudian menunjukkan bagaimana menerapkan loop FOR dan WHILE dasar, dan pada saat itu kami memiliki bahasa dasar seperti Turing-complete C. Saya menemukan itu memuaskan.

GMB
sumber
6

Saya sedang berpikir tentang bagaimana meyakinkan diri saya bahwa mesin Turing adalah model umum perhitungan. Saya setuju bahwa perlakuan standar tesis Church-Turing dalam beberapa buku teks standar, misalnya Sipser, tidak terlalu lengkap. Berikut ini adalah sketsa bagaimana saya bisa beralih dari mesin Turing ke bahasa pemrograman yang lebih dikenal.

Pertimbangkan bahasa pemrograman dengan ifdan whilepernyataan blok-terstruktur , dengan fungsi dan subrutin yang didefinisikan non-rekursif , dengan variabel acak bernama boolean dan ekspresi boolean umum, dan dengan array boolean tunggal tanpa tape[n]batas dengan pointer bilangan bulat integer nyang dapat ditambahkan atau dikurangi, n++atau n--. Pointer nawalnya nol dan array tapeawalnya semua nol. Jadi, bahasa komputer ini bisa seperti C atau Python, tetapi sangat terbatas dalam tipe datanya. Bahkan, mereka sangat terbatas sehingga kita bahkan tidak memiliki cara untuk menggunakan pointer ndalam ekspresi boolean. Berasumsi bahwatapehanya infinite ke kanan, kita dapat mendeklarasikan pointer underflow "kesalahan sistem" jika npernah negatif. Juga, bahasa kita memiliki exitpernyataan dengan satu argumen, untuk menghasilkan jawaban boolean.

Kemudian poin pertama adalah bahwa bahasa pemrograman ini adalah bahasa spesifikasi yang baik untuk mesin Turing. Anda dapat dengan mudah melihat bahwa, kecuali untuk larik kaset, kode hanya memiliki banyak kemungkinan keadaan: Keadaan semua variabel yang dideklarasikan, dan garis eksekusi saat ini, dan tumpukan subrutinnya. Yang terakhir hanya memiliki jumlah negara terbatas karena fungsi rekursif tidak diperbolehkan. Anda dapat membayangkan "kompiler" yang menciptakan mesin Turing "aktual" dari kode jenis ini, tetapi detailnya tidak penting. Intinya adalah bahwa kita memiliki bahasa pemrograman dengan sintaks yang cukup bagus, tetapi tipe data yang sangat primitif.

Sisa konstruksi adalah untuk mengonversikan ini ke bahasa pemrograman yang lebih layak huni dengan daftar fungsi perpustakaan yang terbatas dan tahap-tahap prakompilasi. Kami dapat melanjutkan sebagai berikut:

  1. Dengan precompiler, kita dapat memperluas tipe data boolean ke alfabet simbol yang lebih besar tetapi terbatas seperti ASCII. Kita dapat mengasumsikan bahwa tapemengambil nilai dalam alfabet yang lebih besar ini. Kita dapat meninggalkan marker di awal kaset untuk mencegah pointer underflow, dan marker bergerak di ujung tape untuk mencegah TM dari skating hingga tak terbatas pada tape secara tidak sengaja. Kami dapat menerapkan operasi biner acak antara simbol, dan konversi ke boolean untuk ifdan whilepernyataan. (Sebenarnya ifdapat diimplementasikan dengan whilebaik, jika itu tidak tersedia.)

  2. kksayasayak

  3. Kami menetapkan satu kaset sebagai "memori" yang dihargai simbol dan yang lainnya sebagai "register" atau "variabel" yang dinilai tidak bertanda. Kami menyimpan bilangan bulat dalam biner little-endian dengan marker termination. Kami pertama-tama mengimplementasikan salinan register dan pengurangan biner dari register. Menggabungkannya dengan peningkatan dan penurunan pointer memori, kita dapat mengimplementasikan pencarian akses acak dari memori simbol. Kita juga dapat menulis fungsi untuk menghitung penambahan biner dan perkalian bilangan bulat. Tidak sulit untuk menulis fungsi penambahan biner dengan operasi bitwise, dan fungsi untuk mengalikan 2 dengan shift kiri. (Atau benar-benar bergeser, karena ini adalah little-endian.) Dengan primitif ini, kita dapat menulis fungsi untuk melipatgandakan dua register menggunakan algoritma multiplikasi panjang.

  4. Kita dapat mengatur ulang rekaman memori dari lambang simbol satu dimensi ke lambang simbol symbol[n]dua dimensi symbol[x,y]menggunakan rumus n = (x+y)*(x+y) + y. Kita sekarang dapat menggunakan setiap baris memori untuk mengekspresikan integer yang tidak ditandai dalam biner dengan simbol terminasi, untuk mendapatkan memori satu dimensi, akses acak, bernilai integer memory[x]. Kita dapat mengimplementasikan pembacaan dari memori ke register integer, dan menulis dari register ke memori. Banyak fitur sekarang dapat diimplementasikan dengan fungsi: Aritmatika titik yang ditandatangani dan mengambang, string simbol, dll.

  5. Hanya satu fasilitas dasar lagi yang benar-benar membutuhkan precompiler, yaitu fungsi rekursif. Ini dapat dilakukan dengan teknik yang banyak digunakan untuk mengimplementasikan bahasa yang ditafsirkan. Kami menetapkan setiap string tingkat tinggi, fungsi rekursif nama, dan kami mengatur kode tingkat rendah menjadi satu whileloop besar yang mempertahankan tumpukan panggilan dengan parameter biasa: titik panggilan, fungsi yang dipanggil, dan daftar argumen.

Pada titik ini, konstruksi memiliki fitur yang cukup dari bahasa pemrograman tingkat tinggi yang fungsionalitas lebih lanjut lebih merupakan topik bahasa pemrograman dan kompiler daripada teori CS. Juga sudah mudah untuk menulis simulator mesin Turing dalam bahasa yang dikembangkan ini. Memang tidak mudah, tetapi tentu standar, untuk menulis self-compiler untuk bahasa tersebut. Tentu saja Anda memerlukan kompiler luar untuk membuat TM luar dari kode dalam bahasa seperti C atau Python, tetapi itu bisa dilakukan dalam bahasa komputer apa pun.

Perhatikan bahwa implementasi sketsa ini tidak hanya mendukung tesis Church-Turing ahli logika untuk kelas fungsi rekursif, tetapi juga tesis Church-Turing diperpanjang (yaitu, polinomial) yang berlaku untuk perhitungan deterministik. Dengan kata lain, ia memiliki overhead polinomial. Bahkan, jika kita diberi mesin RAM atau (favorit pribadi saya) pohon-tape TM, ini dapat direduksi menjadi overhead polylogarithmic untuk perhitungan serial dengan memori RAM.

Greg Kuperberg
sumber
5

Kompiler LLVM memungkinkan seseorang untuk cukup "mencolokkan" sebuah arsitektur baru. Mereka menyebut tulisan ini sebagai back-end baru , dan memberikan instruksi dan contoh terperinci untuk bagaimana melakukannya. Saya menduga Anda harus melewati beberapa rintangan sehubungan dengan memori akses acak, jika Anda tidak ingin menargetkan mesin RAM Turing, tapi ini pasti bisa dilakukan, karena saya telah melihat sejumlah proyek yang menyebabkan LLVM menghasilkan VHDL atau bahasa mesin lainnya yang sangat berbeda.

Ini akan memiliki efek menarik dari memiliki kompilator pengoptimal yang canggih (dalam banyak hal LLVM lebih maju daripada GCC) menghasilkan kode untuk mesin Turing.

apw
sumber
1

Saya tidak dalam teori cs tetapi saya memiliki sesuatu yang mungkin berguna. Saya telah mengambil pendekatan lain. Saya merancang prosesor sederhana yang langsung dapat diprogram dengan sub-set kecil dari C. Tidak ada kode perakitan, hanya kode C-like. Anda dapat menggunakan alat yang sama yang saya gunakan dan memodifikasi prosesor ini untuk merancang simulator mesin Turing Anda. Butuh 4 hari bagi saya untuk merancang, mensimulasikan dan menguji prosesor ini, juga beberapa instruksi! Alat yang saya gunakan bahkan memungkinkan saya untuk menghasilkan kode VHDL nyata yang dapat disintesis. Ini adalah prosesor yang benar-benar berfungsi.

Seperti apa bentuk programnya: Contoh Program Perakitan C-Like

Berikut adalah gambar prosesor menggunakan Alat tesis .: Sirkuit Prosesor

Alat "Novakod Studio" menggunakan Bahasa Deskripsi Perangkat Keras Bahasa Tingkat Tinggi. Sebagai contoh, berikut adalah kode penghitung program: PSC - Sampel kode C paralel dan sinkron Cukup berbicara, jika ada yang tertarik, inilah informasi publik untuk menghubungi saya: https://repertoire.uqac.ca/Fiche.aspx?id=JjstNzsH0&link=1

Luc

Luc Morin
sumber
apakah pengalamatan memori menggunakan # bit yang tetap untuk mencari alamat?
vzn
Ya, tetapi mudah untuk mengubah ukuran memori (int DataMemory [SIZE]. Bahasa ini mendukung integer panjang variabel (int: 10). Namun, karena menargetkan FPGA, array bersifat statis dan dimensi konstan
Luc Morin
1

Bagaimana dengan mengambil ide yang diwakili oleh pengguna GMB di sini (Mesin Turing dengan satu pita dapat mensimulasikan mesin Turing dengan pita N dengan menghubungkan pita N ke satu kaset dan membaca salah satu dari kaset itu dengan melompat ke lokasi N pada satu waktu, sebuah Turing mesin dengan kaset N dapat mengimplementasikan ...) dan menulis program mesin Turing yang mengimplementasikan mesin RAM sederhana. Mesin RAM sebenarnya mungkin beberapa CPU sederhana, nyata, dengan LLVM atau GCC backend yang tersedia. Kemudian GCC / LLVM dapat digunakan untuk mengkompilasi silang program C untuk CPU itu dan program mesin Turing yang mensimulasikan mesin RAM, menjalankan simulasi mesin RAM dengan meminta mesin simulasi SIM menjalankan mesin GCC / LLVM output. Implementasi mesin Turing mungkin beberapa kode C sangat sederhana yang cocok untuk file C kecil.

Apa yang berkaitan dengan mesin RAM, maka ada proyek demo, di mana CPU 32bit disimulasikan oleh mikrokontroler 8bit dan CPU 32bit simulasi mem-boot Linux. Lambat sekali, tetapi menurut penulis , Dmitry Grinberg, itu berhasil. Mungkin Zylin CPU (GitHub user zylin) mungkin menjadi pilihan yang layak untuk mesin RAM simulatable. Calon mesin RAМ lainnya mungkin adalah ProjectOberon dot com oleh Niklaus Wirth .

("Titik" dan "com" dalam teks saya disebabkan oleh fakta bahwa saya baru saja, 2015_10_21, mendaftarkan akun saya di cstheory.stackexchange dan aplikasi web tidak mengizinkan lebih dari 2 tautan untuk pengguna pemula, meskipun faktanya bahwa mereka dapat secara otomatis melihat dari akun stackexchange saya yang lain bahwa saya mungkin bodoh, tapi saya bukan troll.)

Martin Vahi
sumber