Algoritma mana yang dapat diekspresikan menggunakan bahasa fungsional total dengan operator paralel data?

11

Bayangkan sebuah bahasa pemrograman fungsional yang hanya tipe datanya berupa skalar numerik dan susunan array yang sewenang-wenang. Bahasa tidak memiliki sarana iterasi tanpa batas, jadi yang berikut ini tidak diizinkan:

  • loop eksplisit (tidak banyak digunakan tanpa efek samping)
  • pengulangan
  • fungsi kelas satu yang arbitrer (tidak ada kombinator)

Namun, bahasa tersebut memiliki:

  • fungsi tingkat atas
  • ikatan mengikat lexically lexically
  • kontrol aliran bercabang
  • fungsi skalar matematika dan logika umum
  • beberapa konstruktor array sederhana seperti isian (n, x) yang membuat array n-elemen dengan nilai identik x
  • yang paling penting: seperangkat terbatas operator tingkat tinggi yang melakukan iterasi terstruktur paralel (seperti peta, perkecil, pindai, semua-pasangan).

Untuk lebih spesifik tentang operator paralel data:

  • y = peta (f, x) => y [i] = f [i]
  • y = mengurangi (f, a, x) => y = f (a, f (y [p [0]], f (y [p [1]], ...))) untuk beberapa permutasi p
  • y = memindai (f, a, x) => y [i] = mengurangi (f, a, y [0 ... i-1])
  • y = semua pasangan (f, x, y) => y [i, j] = f (x [i], y [j])

Kita dapat memiliki operator lain juga, tetapi untuk memenuhi syarat mereka harus memiliki waktu berjalan polinomial, dapat diimplementasikan di bawah beberapa model yang wajar dari perhitungan paralel data, dan digunakan di sebagian besar ruang polinomial.

Jelas ada beberapa konstruksi yang tidak dapat diekspresikan dalam bahasa ini, seperti:

while f(x) > tol:
    x <- update(x)   

Apa yang bisa kami ungkapkan dalam sistem ini? Apakah kita hanya terbatas pada masalah pencarian di FP? Bisakah kita menangkap semua algoritma waktu polinomial? Juga, apakah ada beberapa set minimal operator untuk kelas ini?

Alex Rubinsteyn
sumber

Jawaban:

7

Anda mungkin ingin melihat bahasa pemrograman lama NESL yang menganggap serius ide-ide ini. Bahasa didasarkan pada operasi pada koleksi, pada dasarnya daftar dan daftar daftar dan sebagainya, tapi saya pikir pohon dan grafik juga dipertimbangkan, melalui penyandian yang rumit. Beberapa penelitian yang dilakukan dalam proyek itu (pada pertengahan 1990-an) dapat membantu menjawab pertanyaan Anda. Tesis PhD (tersedia sebagai buku) Guy E. Blelloch. Model Vektor untuk Komputasi Data-Paralel. MIT Press, 1990 dapat memberikan beberapa jawaban. Beberapa waktu yang lalu sejak saya melihatnya.

Pekerjaan yang dilakukan pada Formalisme Meertens Burung (BMF) termasuk dalam kategori ini juga, seperti halnya bahasa Amal . Dari halaman wikipedia Charity dikatakan bahwa bahasa tersebut tidak lengkap Turing, tetapi dapat mengekspresikan fungsi Ackermann, yang berarti bahwa itu lebih dari rekursif primitif. Baik BMF dan Charity melibatkan operator seperti lipatan dan pindaian (katamorfisme, anamorfisme, dll.), Dan mereka berakar pada Kategori Teori.

Saya singkat, jawaban yang tidak tepat adalah bahwa Anda dapat mengekspresikan cukup banyak.

Dave Clarke
sumber
1
NESL bukan bahasa total.
Per Vognsen
Saya telah secara dangkal menyadari NESL untuk sementara waktu tetapi hanya membaca salah satu makalah Blelloch secara detail untuk pertama kalinya. Terima kasih atas tipnya. NESL sangat mirip dengan bahasa yang saya jelaskan di atas kecuali bahwa, sebagaimana Per Vognsen perhatikan, itu memungkinkan rekursi.
Alex Rubinsteyn
Saya juga tertarik dengan pilihan operator primitif Blelloch: peta, dist (saya percaya sama dengan apa yang saya sebut 'isi'), panjang, baca-array, tulis-array, pindai, partisi, ratakan. Apakah primitif NESL "lengkap", atau adakah operasi lain dengan implementasi paralel data yang tidak dapat diekspresikan secara efisien menggunakan ini?
Alex Rubinsteyn
2
Hapus rekursi, maka Anda memiliki bahasa yang cukup ekspresif, terutama jika Anda mempertimbangkan lipatan dan sebagainya. Melihat BMF dan pekerjaan yang mengikutinya mungkin lebih menarik. Maaf, tapi saya tidak terkini di bidang ini.
Dave Clarke
7

Jawaban saya yang lain menunjukkan kekurangan dalam bahasa yang digunakan. Dalam jawaban ini saya akan memberikan rincian lebih lanjut tentang masalah dengan koeksistensi lipatan dan terungkap dalam bahasa total. Kemudian saya akan mengusulkan resolusi dan menunjukkan bahwa semua masalah dalam P (dan memang banyak lagi) dapat diselesaikan dalam bahasa yang diperluas ini.

Melipat dalam bahasa total akan menggunakan daftar:

fold :: (a -> b -> b) -> b -> List a -> b

Berlangsung dalam bahasa total menghasilkan aliran, yang berpotensi tidak terikat:

unfold :: (b -> Maybe (a, b)) -> b -> Stream a

Sayangnya, daftar dan aliran hidup di dunia yang berbeda, sehingga operator ini tidak dapat dikomposisikan. Kami membutuhkan korespondensi parsial:

stream :: List a -> Stream a
list :: Int -> Stream a -> List a

Operator aliran menanamkan daftar ke aliran terbatas. Fungsi daftar mengekstrak elemen n pertama (atau lebih sedikit jika aliran berakhir sebelumnya) ke dalam daftar. Dengan demikian, kami memiliki persamaan berikut:

for all xs :: List a, xs == list (length xs) (stream xs)

Sebagai optimalisasi efisiensi, kami sepenuhnya dapat memotong aliran sebagai struktur data perantara:

unfoldList :: Int -> (b -> Maybe (a, b)) -> b -> List a

Sekarang saya akan membuat sketsa bukti bahwa ini (dengan operator lain sudah tersirat dalam pertanyaan awal) memungkinkan kita mensimulasikan algoritma waktu polinomial.

Menurut definisi, bahasa L adalah dalam P ketika ada mesin Turing M dan polinom p sehingga keanggotaan x dalam L dapat diputuskan dengan menjalankan M paling banyak iterasi p (n) di mana n = | x |. Dengan argumen standar, keadaan pita mesin dalam iterasi k dapat dikodekan dengan daftar panjang paling banyak 2k +1, meskipun pita mesin itu tak terbatas.

Idenya sekarang adalah untuk mewakili transisi M sebagai fungsi dari daftar ke daftar. Pengerjaan mesin akan dilakukan dengan membuka keadaan awal dengan fungsi transisi. Ini menghasilkan aliran daftar. Asumsi bahwa L dalam P berarti kita tidak perlu melihat lebih jauh dari elemen p (n) ke dalam aliran. Dengan demikian kita dapat menyusun lipatan dengan list p(n)untuk mendapatkan daftar yang terbatas. Akhirnya, kami melipatnya untuk memeriksa apakah jawaban untuk masalah keputusan itu ya atau tidak.

Lebih umum, ini menunjukkan bahwa setiap kali kita memiliki algoritma yang waktu penghentiannya dapat dibatasi oleh fungsi yang dapat dihitung dalam bahasa, kita dapat mensimulasikannya. Ini juga menunjukkan mengapa sesuatu seperti fungsi Ackermann tidak dapat disimulasikan: itu adalah batasannya sendiri, jadi ada masalah ayam dan telur.

Per Vognsen
sumber
4

Ini adalah bahasa yang sangat berpalut. Coba pemrograman fungsi faktorial:

fact 0 = 1
fact n = n * fact (n-1)

Masalahnya adalah bahasa Anda hanya memiliki lipatan tetapi tidak terbuka. Cara alami mengekspresikan faktorial adalah dengan menyusun lipatan n ke dalam daftar [1, 2, ..., n] dengan lipatan yang merobeknya sambil mengalikan.

Apakah Anda benar-benar tertarik dengan bahasa spesifik ini atau pada pemrograman fungsional total secara umum? Jelas bahwa bahasa Anda paling banyak dapat mengekspresikan algoritma waktu polinomial. Sistem F (kalkulus lambda polimorfik) dapat mengekspresikan monster seperti fungsi Ackermann dengan mudah. Bahkan jika minat Anda pada algoritma waktu polinomial, Anda sering membutuhkan ruang siku super polinomial untuk mengekspresikannya secara alami.

Sunting: Seperti yang ditunjukkan Dave, NESL adalah salah satu dari bahasa pemrograman paralel-fungsional data mani tetapi sangat jauh dari total (bahkan tidak mencoba). Keluarga APL memiliki jalur paralel evolusi dan memiliki subset aljabar total (hindari operator fixed-point). Jika fokus pertanyaan Anda adalah totalitas, David Turner telah menulis beberapa makalah yang bagus di bidang ini meskipun tidak secara khusus pada pemrograman data-paralel.

Per Vognsen
sumber
Maaf, kurangnya operator yang membuka lipatan adalah kekhilafan dari saya ... Saya bermaksud menambahkan satu tetapi lupa memasukkannya ke dalam pos. Saya tidak tertarik dengan bahasa khusus ini, tetapi lebih pada ekspresi dan batasan perhitungan paralel data.
Alex Rubinsteyn
Unfolding secara alami dinilai aliran, bukan nilai array, yang merupakan masalah mendasar dengan koreksi dalam bahasa ketat total.
Per Vognsen