Apa yang kita ketahui tentang program yang terbukti benar?

37

Semakin kompleksnya program komputer dan semakin pentingnya posisi komputer dalam masyarakat kita membuat saya bertanya-tanya mengapa kita masih belum secara kolektif menggunakan bahasa pemrograman di mana Anda harus memberikan bukti formal bahwa kode Anda berfungsi dengan benar.

Saya percaya istilah ini adalah 'kompiler sertifikasi' (saya menemukannya di sini ): kompiler mengkompilasi bahasa pemrograman di mana seseorang tidak hanya harus menulis kode, tetapi juga menyatakan spesifikasi kode dan membuktikan bahwa kode mematuhi spesifikasi (atau gunakan pepatah otomatis untuk melakukannya).

Saat mencari di internet, saya hanya menemukan proyek yang menggunakan bahasa pemrograman yang sangat sederhana atau proyek gagal yang mencoba menyesuaikan bahasa pemrograman modern. Ini mengarahkan saya ke pertanyaan saya:

Apakah ada kompiler sertifikasi yang menerapkan bahasa pemrograman full-blown, atau apakah ini sangat sulit / secara teori tidak mungkin?

Selain itu, saya belum melihat adanya kelas kerumitan yang melibatkan program yang dapat dibuktikan, seperti 'kelas semua bahasa yang dapat diputuskan oleh mesin Turing yang ada buktinya bahwa mesin Turing ini berhenti', yang saya sebut ProvableR , sebagai analog dengan R , himpunan bahasa rekursif.

Saya dapat melihat keuntungan dari mempelajari kelas kompleksitas seperti itu: misalnya, untuk ProvableR masalah Putus dapat ditentukan (saya bahkan menduga ProvableRE didefinisikan dengan cara yang jelas adalah kelas bahasa terbesar yang dapat dipilih). Selain itu, saya ragu kami akan mengesampingkan program praktis yang berguna: siapa yang akan menggunakan program ketika Anda tidak dapat membuktikannya berakhir?

Jadi pertanyaan kedua saya adalah:

Apa yang kita ketahui tentang kelas kompleksitas yang membutuhkan bahasa mereka yang mengandung memiliki properti tertentu?

Alex ten Brink
sumber
1
Kompiler dapat menghitung semua kemungkinan bukti panjang i, membiarkan saya beralih dari 1 hingga tak terbatas, hingga menemukan bukti bahwa program berhenti. Jika kita mengharuskan input untuk kompiler terbukti terhenti, maka kompiler akan selalu menemukan bukti itu. Karena masalah penghentian tidak dapat diputuskan, kita harus menyimpulkan ada program yang berhenti, tetapi tidak ada bukti untuk ini. Poin penting adalah bahwa program tidak dapat menemukan apakah ada bukti, bukan bahwa mereka tidak dapat menemukan bukti jika ada.
Alex ten Brink
3
Saya pikir Anda harus membaginya. Mereka adalah pertanyaan yang berbeda dengan jawaban yang berbeda.
Mark Reitblatt
4
Pada pertanyaan pertama, makalah yang berpengaruh adalah "Proses sosial dan bukti teorema dan program", portal.acm.org/citation.cfm?id=359106
Colin McQuillan
1
Verifikasi program tidak dapat ditentukan. Jadi satu masalah adalah mengatakan apa yang merupakan solusi yang baik. Lihat cstheory.stackexchange.com/questions/4016/…
Radu GRIGore
2
@Colin: makalah itu layak dibaca untuk analisis buktinya, tetapi prediksinya telah dipalsukan. Hari ini kami telah membuktikan kompiler yang benar, kernel sistem operasi, pengumpul sampah, dan basis data, yang semuanya mereka perkirakan mustahil. Trik untuk menghindari kritik mereka adalah menghindari verifikasi manusia terhadap rincian tingkat rendah bukti formal, tetapi menggunakan verifikasi mesin bukti, dan menggunakan manusia untuk memverifikasi pemeriksa bukti. Ref Noam untuk mengetik teori adalah di mana keadaan seni, yang meninggalkan program penting dalam sesuatu yang mengikat karena teori jenis fungsional.
Neel Krishnaswami

Jawaban:

28

"Penyusun penyertifikasi" biasanya berarti sesuatu yang sedikit berbeda: itu berarti Anda memiliki penyusun yang dapat membuktikan bahwa kode mesin yang dipancarkannya dengan benar mengimplementasikan semantik tingkat tinggi. Artinya, ini adalah bukti bahwa tidak ada bug kompiler. Program yang diberikan orang ke kompiler masih bisa salah, tetapi kompiler akan menghasilkan versi kode mesin yang benar dari program yang salah. Kisah sukses terbesar di sepanjang baris ini adalah kompiler terverifikasi CompCert , yang merupakan kompiler untuk sebagian besar dari C.

Compiler Compcert itu sendiri adalah sebuah program dengan bukti kebenaran (dilakukan dalam Coq), yang menjamin bahwa jika menghasilkan kode untuk suatu program, itu akan benar (sehubungan dengan semantik operasional perakitan & C yang digunakan desainer CompCert). Upaya memeriksa mesin-mesin ini cukup besar; biasanya bukti kebenarannya berkisar antara 1x hingga 100x ukuran program yang Anda verifikasi. Menulis program dan bukti yang diperiksa dengan mesin adalah keterampilan baru yang harus Anda pelajari - ini bukan matematika atau pemrograman seperti biasa, meskipun itu tergantung pada kemampuan untuk melakukan keduanya dengan baik. Rasanya seperti Anda mulai dari awal, seperti menjadi programmer pemula lagi.

Tidak ada hambatan teoretis khusus untuk ini. Satu-satunya hal di sepanjang baris ini adalah teorema Blum Size bahwa untuk semua bahasa di mana semua program total, Anda dapat menemukan program dalam bahasa rekursif umum yang akan setidaknya secara eksponensial lebih besar ketika diprogram dalam bahasa total. Cara untuk memahami hasil ini adalah bahwa bahasa total mengkodekan tidak hanya sebuah program, tetapi juga bukti terminasi. Jadi, Anda dapat memiliki program pendek dengan bukti terminasi panjang. Namun, ini tidak terlalu penting dalam praktik, karena kita hanya akan pernah menulis program dengan bukti terminasi yang dapat dikelola.

EDIT: Dai Le meminta penjelasan tentang poin terakhir.

Ini sebagian besar merupakan klaim pragmatis, berdasarkan pada fakta bahwa jika Anda dapat memahami mengapa suatu program bekerja, maka tidak mungkin bahwa alasannya adalah berjuta-juta halaman sepanjang invarian. (Invarian terpanjang yang pernah saya gunakan adalah beberapa halaman, dan apakah mereka membuat pengulas menggerutu! Dapat dimengerti juga, karena invarian adalah alasan mengapa program bekerja menghilangkan semua narasi yang membantu orang memahaminya.)

Tetapi ada juga beberapa alasan teoretis juga. Pada dasarnya, kita tidak tahu banyak cara untuk secara sistematis menciptakan program yang bukti kebenarannya sangat panjang. Metode utama adalah (1) mengambil logika di mana Anda membuktikan kebenaran, (2) menemukan properti yang tidak dapat secara langsung dinyatakan dalam logika itu (bukti konsistensi adalah sumber khas), dan (3) menemukan program yang bukti kebenaran bergantung pada keluarga konsekuensi yang dapat diungkapkan dari properti yang tidak dapat diungkapkan. Karena (2) tidak dapat diekspresikan, ini berarti bahwa bukti dari setiap konsekuensi yang dapat diekspresikan harus dilakukan secara independen, yang memungkinkan Anda meledakkan ukuran bukti kebenaran. Sebagai contoh sederhana, perhatikan bahwa dalam logika tingkat pertama dengan relasi induk, Anda tidak bisa mengekspresikan relasi leluhur.kk) dapat diekspresikan, untuk setiap tetap . Jadi dengan memberikan program yang menggunakan beberapa properti leluhur hingga beberapa kedalaman (katakanlah, 100), Anda dapat memaksa bukti kebenaran dalam FOL untuk memuat bukti dari properti tersebut seratus kali lipat.k

Pandangan canggih tentang subjek ini disebut "matematika terbalik", dan merupakan studi yang mengharuskan aksioma untuk membuktikan teorema yang diberikan. Saya tidak tahu banyak tentang itu, tetapi jika Anda memposting pertanyaan tentang aplikasinya ke CS, dan saya yakin setidaknya Timothy Chow, dan mungkin beberapa orang lain, akan dapat memberi tahu Anda hal-hal menarik.

Neel Krishnaswami
sumber
1
Bisakah Anda jelaskan poin ini "kita hanya akan pernah menulis program dengan bukti terminasi dikelola" sedikit lebih?
Dai Le
Terima kasih atas jawaban Anda yang diperbarui! Jawaban Anda benar-benar membuka perspektif saya. Sebenarnya saya sendiri juga bekerja sedikit pada "matematika terbalik", tetapi saya tidak menyadari koneksi yang Anda sebutkan. Terima kasih lagi!
Dai Le
1
Poin dalam suntingan Anda terkait dengan fakta bahwa kami hampir tidak memiliki kandidat untuk tautologi yang memerlukan bukti panjang dalam sistem bukti alami (seperti, katakanlah, Frege). Salah satu alasan untuk ini adalah bahwa satu-satunya cara kita mengetahui tautologi adalah tautologous adalah karena kita memiliki bukti dalam pikiran, yang tentu saja tidak begitu lama!
Joshua Grochow
22

Saya pikir jawaban untuk pertanyaan pertama adalah bahwa umumnya terlalu banyak bekerja dengan alat saat ini. Untuk mendapatkan perasaan, saya sarankan mencoba untuk membuktikan kebenaran Bubble Sort dalam Coq (atau jika Anda lebih suka sedikit tantangan, gunakan Quick Sort). Saya tidak berpikir masuk akal untuk mengharapkan programmer menulis program yang diverifikasi asalkan membuktikan kebenaran dari algoritma dasar seperti itu sangat sulit dan memakan waktu.

Pertanyaan ini mirip dengan menanyakan mengapa ahli matematika tidak menulis bukti formal yang dapat diverifikasi oleh pemeriksa bukti? Menulis program dengan bukti kebenaran formal berarti membuktikan teorema matematika tentang kode tertulis, dan jawaban untuk pertanyaan itu juga berlaku untuk pertanyaan Anda.

Ini tidak berarti bahwa belum ada kasus yang berhasil dari program yang diverifikasi. Saya tahu bahwa ada kelompok yang membuktikan kebenaran sistem seperti hypervisor Microsoft . Kasus terkait adalah Microsoft C Compiler Terverifikasi . Tetapi secara umum alat saat ini membutuhkan banyak pengembangan (termasuk aspek SE dan HCI mereka) sebelum menjadi berguna bagi programmer umum (dan ahli matematika).

Mengenai paragraf terakhir dari jawaban Neel tentang pertumbuhan ukuran program untuk bahasa dengan hanya fungsi total, sebenarnya mudah untuk membuktikan lebih banyak lagi (Jika saya memahaminya dengan benar). Adalah masuk akal untuk mengharapkan bahwa sintaks dari bahasa pemrograman apa pun akan ce dan himpunan fungsi komputasi total tidak ce, jadi untuk bahasa pemrograman mana pun semua program total ada fungsi komputasi total yang tidak dapat dihitung oleh program apa pun ( dalam ukuran berapa pun) dalam bahasa itu.


Untuk pertanyaan kedua, saya menjawab pertanyaan serupa di blog Scott beberapa waktu yang lalu. Pada dasarnya jika kelas kompleksitas memiliki karakterisasi yang bagus dan dapat dihitung secara representatif (yaitu ce) maka kita dapat membuktikan bahwa beberapa representasi masalah dalam kelas kompleksitas terbukti total dalam teori yang sangat lemah sesuai dengan kelas kompleksitas. Ide dasarnya adalah bahwa provably keseluruhan fungsi dari teori berisi semua fungsi dan masalah yang A C 0AC0AC0-lengkap untuk kelas kompleksitas, oleh karena itu berisi semua masalah di kelas kompleksitas dan dapat membuktikan totalitas program-program tersebut. Hubungan antara bukti dan teori kompleksitas dipelajari dalam kompleksitas bukti, lihat buku terbaru SA Cook dan P. Nguyen " Yayasan Logistik Kompleksitas Bukti " jika Anda tertarik. ( Draf dari 2008 tersedia.) Jadi jawaban dasarnya adalah bahwa untuk banyak kelas "Terbukti C = C".

Ini tidak benar secara umum karena ada kelas kompleksitas semantik yang tidak memiliki karakterisasi sintaksis, misalnya total fungsi yang dapat dihitung. Jika dengan rekursif yang Anda maksud adalah fungsi rekursif total maka keduanya tidak sama, dan himpunan fungsi yang dapat dihitung yang terbukti total dalam suatu teori dipelajari dengan baik dalam literatur teori pembuktian dan disebut fungsi total yang dapat dibuktikan dari teori. Sebagai contoh: provably Total fungsi adalah ε 0 fungsi -recursive (atau ekuivalen fungsi dalam sistem Godel T ), yang provably keseluruhan fungsi dari P A 2 adalah fungsi dalam Girard sistem F , yang provably Total fungsiPAϵ0TPA2F adalah fungsi rekursif primitif, ....IΣ1

Tetapi bagi saya tampaknya hal ini tidak banyak berarti dalam konteks verifikasi program, karena ada juga program yang secara komputasi menghitung fungsi yang sama tetapi kami tidak dapat membuktikan bahwa kedua program tersebut menghitung fungsi yang sama, yaitu program-program tersebut secara ekstensi sama tetapi tidak sengaja. (Ini mirip dengan Bintang Fajar dan Bintang Sore.) Selain itu, mudah untuk memodifikasi program total terbukti yang diberikan untuk mendapatkan satu yang teorinya tidak dapat membuktikan totalitasnya.


PnnPalgoritma untuk faktorisasi dari buktinya. (Ada juga peneliti yang mencoba mengotomatiskan pendekatan pertama sebanyak mungkin, tetapi memeriksa properti non-sepele yang menarik dari program sulit secara komputasi dan tidak dapat sepenuhnya diverifikasi tanpa positif dan negatif palsu.)

Kaveh
sumber
3
Jawaban bagus! Anda menyebutkan bahwa salah satu caranya adalah mengekstrak program dari bukti, yang dapat dilakukan secara otomatis dalam Coq, misalnya. Bidang terkait adalah penambangan bukti , di mana orang-orang (biasanya bekerja dalam logika matematika) mencoba mengekstraksi informasi dari bukti yang diberikan. Misalnya, dalam beberapa kasus dimungkinkan (secara otomatis) menemukan bukti intuitionistic yang diberikan bukti klasik.
Radu GRIGore
1
Π20PAHA
1
Andrej Bauer memiliki posting baru yang menarik di blognya di mana ia membuktikan Godel's Dialectica Interpretation in Coq .
Kaveh
18

Apa yang Anda tanyakan dalam pertanyaan pertama kadang-kadang disebut "kompiler verifikasi", dan beberapa tahun yang lalu Tony Hoare menawarkannya sebagai tantangan besar untuk riset komputasi . Hingga taraf tertentu ini sudah ada dan sedang aktif digunakan dalam alat-alat seperti Coor theorem prover , yang mengatur masalah dengan cara teori jenis dan prinsip proposisi-sebagai-tipe (" Curry-Howard ").

EDIT: hanya ingin menambahkan penekanan pada "sampai batas tertentu". Ini jauh dari masalah yang diselesaikan, tetapi keberhasilan Coq memberi harapan bahwa itu bukan mimpi pipa.

Noam Zeilberger
sumber
8
Saya akan mengatakan bahwa membangun perangkat lunak terverifikasi adalah tempat membangun perangkat lunak lama pada tahun 1956. Sudah jelas bahwa perangkat lunak akan menjadi sangat penting, dan sudah ada kisah sukses besar. Namun, orang masih banyak konsep dasar yang hilang (pemahaman yang jelas tentang apa prosedur dan variabel, misalnya), dan jarak dari teori ke praktek bisa sesingkat menerapkan Lisp dengan memprogram kode dalam teorema. Ini adalah waktu yang sangat menarik untuk mengerjakan bahasa dan verifikasi.
Neel Krishnaswami
12

Alat yang memeriksa apakah suatu program benar kadang-kadang disebut verifikasi program. Dalam konteks ini, "benar" biasanya berarti dua hal: bahwa program tidak pernah menghasilkan output tertentu (pikirkan kesalahan segmentasi, NullPointerException, dll.) Dan bahwa program setuju dengan spesifikasi.

Kode dan spesifikasinya mungkin setuju dan masih dianggap salah. Dalam arti tertentu, meminta pengembang untuk menulis spesifikasi seperti meminta dua pengembang untuk menyelesaikan masalah. Jika kedua implementasi setuju maka Anda memiliki keyakinan yang lebih tinggi bahwa mereka baik-baik saja. Namun, dalam arti lain, spesifikasi lebih baik daripada implementasi kedua. Karena spesifikasi tidak perlu efisien atau bahkan dapat dieksekusi, itu bisa jauh lebih ringkas dan karenanya lebih sulit untuk salah.

Dengan peringatan ini dalam pikiran, saya sarankan Anda melihat verifikasi program Spec # .

Radu GRIGore
sumber
Sejauh yang saya mengerti Spec # (dan ekstensi Sing #), itu memberikan programmer kemampuan untuk memverifikasi pernyataan statis, tetapi tidak memerlukan programmer melakukan ini, juga tidak memberikan kemampuan untuk membuktikan sifat sewenang-wenang dari kode.
Alex ten Brink
Sifat sewenang-wenang dapat dikodekan sebagai pernyataan berikut, pada prinsipnya. Saya tidak yakin apa yang Anda inginkan dari alat ini. Apakah Anda ingin spesifikasi mengatakan berapa output yang seharusnya untuk semua input yang mungkin?
Radu GRIGore
4

Dalam kasus umum, tidak mungkin untuk membuat algoritma yang mengkonfirmasi apakah suatu algoritma setara dengan spesifikasi. Ini adalah bukti informal:

Hampir semua bahasa pemrograman Turing-lengkap. Oleh karena itu, bahasa apa pun yang diputuskan oleh TM juga dapat diputuskan oleh program yang ditulis dalam bahasa ini.

Equivalence/TM

Equivalence/TMNonemptiness/TMEmptiness/TMEmptiness/TMEquivalence/TMEquivalence/TMjuga tidak bisa diterima. Karena itu Anda dapat menggunakan suatu algoritma apakah dua mesin tidak setara atau tidak, tetapi Anda tidak dapat memastikan apakah mereka setara, atau Anda belum memberikan algoritma Anda cukup waktu.

Namun, ini hanya untuk kasus umum. Ada kemungkinan bahwa Anda dapat memutuskan apakah spesifikasinya setara dengan program, dengan memecahkan versi masalah yang lebih santai. Misalnya, Anda dapat memeriksa hanya sejumlah input atau mengatakan bahwa kedua program tersebut setara dengan beberapa ketidakpastian. Inilah yang dimaksud dengan pengujian perangkat lunak.

Adapun sisa pertanyaan Anda:

Catatan: Bagian ini telah diedit untuk klarifikasi. Ternyata saya melakukan kesalahan yang saya coba hindari, maaf.

TrueRTrueRR

ProvableR=TrueRProvableRTrueRTrueRProvableRAϵTrueRAAAϵProvableR

Secara informal, ini dapat diringkas sebagai: Anda tidak tahu bahwa suatu bahasa dapat ditentukan sampai Anda membuktikannya. Jadi jika dalam sistem formal Anda memiliki pengetahuan bahwa suatu bahasa dapat dipilih, pengetahuan ini juga dapat berfungsi sebagai bukti untuk itu. Oleh karena itu, Anda tidak dapat secara bersamaan memiliki pengetahuan bahwa suatu bahasa dapat dipilih dan tidak dapat dibuktikan demikian, kedua pernyataan ini saling eksklusif.

RProvableRProvableRRR

@Kaveh merangkumnya dengan sangat baik: Dapat dibuktikan selalu berarti dapat dibuktikan dalam beberapa sistem / teori dan tidak sesuai dengan kebenaran secara umum.

Hal yang sama berlaku untuk kelas kompleksitas lainnya: Untuk menentukan keanggotaan Anda perlu bukti terlebih dahulu. Inilah mengapa saya percaya bahwa pertanyaan kedua Anda terlalu umum, karena tidak hanya berisi teori kompleksitas, tetapi juga teori komputasi, tergantung pada properti yang Anda inginkan bahasa.

chazisop
sumber
1
RProvableRΣ30Σ10
1
Terbukti selalu berarti dapat dibuktikan dalam beberapa sistem / teori dan tidak bertepatan dengan kebenaran secara umum.
Kaveh
1
Saya melihat sekarang bahwa pertanyaan saya menjadi menarik, orang harus berbicara tentang set mesin Turing yang terputus, bukan set bahasa yang dapat dipilih.
Alex ten Brink
1
@ Alex Yah, Anda perlu cara berbicara tentang bahasa, tapi ada banyak sekali. Jadi, jika Anda ingin berbicara tentang bahasa yang terhubung ke beberapa objek hingga (seperti bukti), Anda perlu membatasi diri ke bahasa yang dapat diidentifikasi oleh objek hingga, seperti TM.
Mark Reitblatt
2
R
3

Studi monograf klasik berikut hampir persis dengan pertanyaan kedua Anda:

Hartmanis, J. Perhitungan yang layak dan sifat kompleksitas yang dapat dibuktikan , Seri Konferensi Regional CBMS-NSF dalam Matematika Terapan, 30. Masyarakat untuk Industri dan Matematika Terapan (SIAM), Philadelphia, Pa., 1978.

{L(Mi)|Ti(n)T(n) is provable in F}MiTi(n)Min

T(n)nlog(n)g(n)1FTIME[T(n)]TIME[T(n)g(n)]

T(n)FTIME[T(n)]TIME[T(n)]

T(n)nlog(n)TIME[T(n)]={L(Mi)|F proves(j)[L(Mj)=L(Mi)Tj(n)T(n)]}

Namun untuk ruang, situasinya lebih terkontrol:

s(n)nSPACE[s(n)]=FSPACE[s(n)]

SPACE[S(n)]=FSPACE[S(n)]S(n)ns(n)SPACE[S(n)]=SPACE[s(n)]

Joshua Grochow
sumber
1

Pertanyaan harus diajukan dengan benar. Sebagai contoh, tidak ada yang pernah ingin tahu apakah suatu program aktual akan selesai diberikan memori tak terbatas dan beberapa cara mengaksesnya (mungkin operasi untuk memindahkan alamat pangkalan dengan beberapa nomor). Teorema Turing tidak relevan dengan kebenaran program dalam arti konkret dan orang-orang yang menyebutnya sebagai penghambat verifikasi program membingungkan dua hal yang sangat berbeda. Ketika insinyur / programmer berbicara tentang kebenaran program, mereka ingin tahu tentang properti yang terbatas. Ini juga cukup benar untuk matematikawan yang tertarik pada apakah sesuatu dapat dibuktikan. Surat Godel http://vyodaiken.com/2009/08/28/godels-lost-letter/ menjelaskan hal ini secara terperinci.

Yaitu, itu jelas akan berarti bahwa meskipun keraguan Entscheidungsproblem, pekerjaan mental seorang ahli matematika tentang pertanyaan Ya atau Tidak dapat sepenuhnya diganti oleh mesin. Lagi pula, orang hanya harus memilih bilangan alami dan begitu besar sehingga ketika mesin tidak memberikan hasil, tidak masuk akal untuk berpikir lebih banyak tentang masalahnya.

Mungkin tidak layak untuk memeriksa serangkaian besar program yang dijalankan pada komputer yang sebenarnya dan mendeteksi keadaan yang buruk, tidak ada alasan teoretis mengapa hal itu tidak dapat dilakukan. Faktanya, ada banyak kemajuan di bidang ini - misalnya lihat http://www.cs.cornell.edu/gomes/papers/SATSolvers-KR-book-draft-07.pdf (terima kasih kepada Neil Immerman untuk bercerita tentang ini)

Masalah yang berbeda dan lebih sulit adalah menentukan dengan tepat properti apa yang ingin dimiliki suatu program agar benar.

Victor Yodaiken
sumber