Saya telah melihat seluruh stack Overflow, misalnya di sini , di sini , di sini , di sini , di sini dan beberapa yang lain saya tidak peduli untuk menyebutkan, bahwa "program apa pun yang menggunakan rekursi dapat dikonversi ke program yang hanya menggunakan iterasi".
Bahkan ada utas yang sangat tervvotasikan dengan jawaban yang sangat tervotifikasi yang mengatakan ya itu mungkin.
Sekarang saya tidak mengatakan mereka salah. Hanya saja jawaban itu melawan sedikit pengetahuan dan pemahaman saya tentang komputasi.
Saya percaya setiap fungsi berulang dapat dinyatakan sebagai rekursi, dan wikipedia memiliki pernyataan untuk efek itu. Namun, saya ragu bahwa yang terjadi adalah sebaliknya. Untuk satu, saya ragu fungsi rekursif non-primitif dapat diekspresikan secara iteratif.
Saya juga ragu operasi-hiper dapat diekspresikan secara iteratif.
Dalam jawabannya (yang saya tidak mengerti dengan cara) untuk pertanyaan saya @ YuvalFIlmus mengatakan bahwa tidak mungkin untuk mengubah urutan operasi matematika menjadi urutan penambahan.
Jika jawaban YF memang benar (saya kira begitu, tetapi alasannya berada di atas kepala saya), bukankah ini berarti bahwa tidak setiap rekursi dapat dikonversi menjadi iterasi? Karena jika mungkin untuk mengubah setiap rekursi menjadi iterasi, saya dapat mengekspresikan semua operasi sebagai urutan penambahan.
Pertanyaan saya adalah ini:
Bisakah setiap rekursi dikonversi menjadi iterasi dan mengapa?
Tolong beri jawaban, siswa sekolah menengah yang cerah atau sarjana tahun pertama akan mengerti. Terima kasih.
PS Saya tidak tahu apa itu primitif rekursif (saya tahu tentang fungsi Ackermann, dan itu bukan rekursif primitif, tetapi masih bisa dihitung. ALA pengetahuan saya tentang itu berasal dari halaman Wikipedia pada fungsi Ackermann.)
PPS: Jika jawabannya adalah ya, bisakah Anda misalnya menulis versi berulang dari fungsi non-primitif-rekursif. Misalnya Ackermann dalam jawabannya. Ini akan membantu saya mengerti.
sumber
Jawaban:
Dimungkinkan untuk mengganti rekursi dengan iterasi plus memori tanpa batas .
Jika Anda hanya memiliki iterasi (katakanlah, sementara loop) dan jumlah memori yang terbatas, maka semua yang Anda miliki adalah otomat terbatas. Dengan jumlah memori yang terbatas, perhitungan memiliki sejumlah langkah yang mungkin terbatas, jadi dimungkinkan untuk mensimulasikan semuanya dengan otomat terbatas.
Memori yang tidak terbatas mengubah kesepakatan. Memori tanpa batas ini dapat mengambil banyak bentuk yang ternyata memiliki kekuatan ekspresif yang setara. Sebagai contoh, mesin Turing membuatnya tetap sederhana: ada satu kaset, dan komputer hanya dapat bergerak maju atau mundur pada kaset dengan satu langkah pada satu waktu - tetapi itu cukup untuk melakukan apa pun yang dapat Anda lakukan dengan fungsi rekursif.
Mesin Turing dapat dilihat sebagai model komputer yang diidealkan (finite state machine) dengan beberapa penyimpanan ekstra yang tumbuh sesuai permintaan. Perhatikan bahwa sangat penting bahwa tidak hanya tidak ada batasan pada pita, tetapi bahkan dengan input, Anda tidak dapat memprediksi dengan pasti berapa banyak pita yang akan dibutuhkan. Jika Anda dapat memprediksi (yaitu menghitung) berapa banyak pita yang dibutuhkan dari input, maka Anda dapat memutuskan apakah perhitungan akan berhenti dengan menghitung ukuran pita maksimum dan kemudian memperlakukan seluruh sistem, termasuk pita yang sekarang terbatas, sebagai mesin keadaan terbatas. .
Cara lain untuk mensimulasikan mesin Turing dengan komputer adalah sebagai berikut. Simulasikan mesin Turing dengan program komputer yang menyimpan awal kaset dalam memori. Jika perhitungan mencapai akhir bagian dari pita yang sesuai dengan memori, gantilah komputer dengan komputer yang lebih besar dan jalankan kembali perhitungan.
Sekarang anggaplah Anda ingin mensimulasikan perhitungan rekursif dengan komputer. Teknik-teknik untuk mengeksekusi fungsi rekursif sudah terkenal: setiap pemanggilan fungsi memiliki memori, yang disebut stack frame . Yang terpenting, fungsi rekursif dapat menyebarkan informasi melalui beberapa panggilan dengan mengirimkan variabel ke sekitarnya. Dalam hal implementasi pada komputer, itu berarti bahwa panggilan fungsi dapat mengakses frame stack panggilan induk (grand-) * .
Komputer adalah prosesor - mesin keadaan terbatas (dengan sejumlah besar keadaan, tapi kami sedang melakukan teori komputasi di sini, jadi yang penting adalah bahwa itu terbatas) - ditambah dengan memori terbatas. Mikroprosesor menjalankan satu raksasa sambil memutar: "saat daya menyala, baca instruksi dari memori dan jalankan". (Prosesor nyata jauh lebih kompleks dari itu, tetapi tidak mempengaruhi apa yang dapat mereka hitung, hanya seberapa cepat dan nyaman mereka melakukannya.) Komputer dapat menjalankan fungsi rekursif dengan hanya loop sementara ini untuk memberikan iterasi, ditambah mekanisme untuk mengakses memori, termasuk kemampuan untuk meningkatkan ukuran memori sesuka hati.
Jika Anda membatasi rekursi menjadi rekursi primitif, maka Anda dapat membatasi iterasi hingga iterasi terbatas . Artinya, alih-alih menggunakan loop sementara dengan waktu berjalan yang tidak dapat diprediksi, Anda dapat menggunakan untuk loop di mana jumlah iterasi diketahui di awal loop¹. Jumlah iterasi mungkin tidak diketahui pada awal program: iterasinya sendiri dapat dihitung dengan loop sebelumnya.
Saya bahkan tidak akan membuat sketsa bukti di sini, tetapi ada hubungan intuitif antara beralih dari rekursi primitif ke rekursi penuh, dan beralih dari loop ke loop sementara: dalam kedua kasus, itu melibatkan tidak mengetahui sebelumnya kapan Anda akan berhenti. Dengan rekursi penuh, ini dilakukan dengan operator minimisasi, di mana Anda terus berjalan sampai Anda menemukan parameter yang memenuhi syarat. Dengan while loop, ini dilakukan dengan terus berjalan sampai kondisi loop terpenuhi.
¹ loop dalam bahasa mirip C dapat melakukan iterasi tanpa batas sama seperti , hanya masalah konvensi untuk membatasi mereka untuk iterasi terbatas. Ketika orang berbicara tentang "untuk loop" dalam teori perhitungan, itu berarti hanya loop yang dihitung dari 1 ke n (atau setara).n
for
while
sumber
Setiap rekursi dapat dikonversi menjadi iterasi, seperti yang disaksikan oleh CPU Anda, yang mengeksekusi program arbitrer menggunakan iterasi tak terbatas mengambil-eksekusi. Ini adalah bentuk teorema Böhm-Jacopini . Selain itu, banyak model komputasi Turing-lengkap tidak memiliki rekursi, misalnya mesin Turing dan mesin pencacah .
Fungsi rekursif primitif sesuai dengan program yang menggunakan iterasi terbatas , yaitu, Anda harus menentukan jumlah iterasi yang dijalankan loop terlebih dahulu. Iterasi terikat tidak dapat mensimulasikan rekursi secara umum, karena fungsi Ackermann bukan rekursif primitif. Tetapi iterasi tanpa batas dapat mensimulasikan fungsi yang dapat dihitung sebagian.
sumber
Saya menerapkan ini di Ceylon, Anda dapat menjalankannya di WebIDE , jika Anda mau. (Ini menampilkan tumpukan pada awal setiap iterasi dari loop.)
Tentu saja, ini hanya memindahkan stack panggilan implisit dari rekursi ke stack eksplisit dengan parameter dan mengembalikan nilai.
sumber
Sudah ada beberapa jawaban bagus (yang bahkan tidak bisa saya harapkan untuk bersaing), tetapi saya ingin menyampaikan penjelasan sederhana ini.
Rekursi hanyalah manipulasi tumpukan runtime. Berulang menambahkan bingkai tumpukan baru (untuk permintaan baru fungsi rekursif), dan kembali menghapus bingkai tumpukan (untuk inovasi fungsi rekursif yang baru saja selesai). Rekursi akan menyebabkan sejumlah bingkai tumpukan ditambahkan / dihapus, sampai akhirnya semuanya keluar (semoga!) Dan hasilnya dikembalikan ke pemanggil.
Sekarang, apa yang akan terjadi jika Anda membuat stack Anda sendiri, mengganti panggilan fungsi rekursif dengan mendorong ke stack, diganti kembali dari fungsi rekursif dengan muncul stack, dan memiliki loop sementara yang berjalan sampai stack kosong?
sumber
Sejauh yang saya tahu, dan dalam pengalaman saya sendiri, Anda dapat menerapkan rekursi apa pun sebagai iterasi. Seperti disebutkan di atas, rekursi menggunakan stack, yang secara konsep tidak terbatas, tetapi praktis terbatas (pernahkah Anda mendapatkan pesan stack overflow?). Pada hari-hari awal saya pemrograman (pada kuartal ketiga abad terakhir dari milenium terakhir) saya menggunakan bahasa non-rekursif menerapkan algoritma rekursif dan tidak punya masalah. Saya tidak yakin bagaimana orang akan membuktikannya.
sumber