Cara menangani array selama bukti ketepatan gaya Hoare


11

Dalam diskusi seputar pertanyaan ini , Gilles menyebutkan dengan benar bahwa bukti kebenaran suatu algoritma yang menggunakan array harus membuktikan bahwa tidak ada akses array di luar batas; tergantung pada model runtime, ini akan menyebabkan kesalahan runtime atau akses ke elemen non-array.

Salah satu teknik umum untuk melakukan pembuktian kebenaran tersebut (setidaknya dalam studi sarjana dan mungkin dalam verifikasi otomatis) adalah dengan menggunakan logika Hoare . Saya tidak menyadari bahwa seperangkat aturan standar berisi apa pun yang berkaitan dengan array; mereka tampaknya terbatas pada variabel monadik.

Saya bisa membayangkan menambahkan aksioma bentuk

{0i<A.lengthP[A[i]/E]} A[i]:=E; {P}

Namun, tidak jelas bagi saya bagaimana Anda akan berurusan dengan akses array pada sisi kanan, yaitu jika itu adalah bagian dari ekspresi kompleks dalam beberapa pernyataan .Ex:=E

Bagaimana akses array dapat dimodelkan dalam logika Hoare sehingga tidak adanya akses yang tidak valid dapat dan harus dibuktikan untuk kebenaran program?

Jawaban dapat berasumsi bahwa kami melarang elemen array untuk digunakan dalam pernyataan selain atau sebagai bagian dari beberapa dalam karena ini tidak membatasi ekspresif; kita selalu dapat menetapkan variabel sementara nilai yang diinginkan, yaitu menulis daripada .E x : = E t : = A [ i ] ; i f ( t > 0 ) ... i f ( A [ i ] > 0 ) ...A[i]:=EEx:=Et:=A[i]; if(t>0)if(A[i]>0)

Jawaban:


8

Aksioma Anda bukan benar-benar aksioma, ini hipotesis yang hilang. Presentasi sederhana dari logika Hoare memanipulasi rumus bentuk mana dan adalah rumus logis dan adalah sebuah perintah. Anda perlu memastikan bahwa terbentuk dengan baik . Dalam bahasa sederhana seperti yang sering digunakan untuk pengenalan pertama yang Hoare logika, baik-formedness adalah sintaksis: itu biasanya masalah memeriksa bahwaP P C C C{P}C{P}PPCCCsesuai dengan tata bahasa bebas konteks, dan mungkin bahwa variabel bebas berada dalam set yang diizinkan. Jika bahasa menyertakan konstruk yang memiliki kebenaran semantik, seperti akses ke elemen array, Anda perlu menambahkan hipotesis untuk mengekspresikan kebenaran semantik ini.

Secara formal, Anda dapat menambahkan penilaian untuk mengekspresikan koreksi ekspresi dan perintah. Jika ekspresi tidak memiliki efek samping, mereka tidak memerlukan kondisi akhir, hanya kondisi awal. Misalnya, Anda dapat menulis aturan yang terbentuk dengan baik seperti dan hanya memungkinkan ekspresi yang terbentuk dalam perintah:

{P}E wf{P0E<length(A)}A[E] wf{P}E1 wf{P}E2 wf{P}E1+E2 wf
{P[xE]}E wf{P[xE]}x:=E{P}

Pendekatan yang berbeda adalah memperlakukan semua ekspresi sebagai well-formed, tetapi untuk membuat ekspresi apa pun yang melibatkan penghitungan yang salah memiliki nilai khusus . Dalam bahasa dengan pemeriksaan run-time bounds, berarti "program ini menimbulkan pengecualian fatal". Anda kemudian akan melacak apakah suatu program salah melalui predikat logiserrorerrorError¬Error

{P[xE]}x:=E{PError}P[xE]Eerror{P[xE]}x:=E{P}

Namun pendekatan lain adalah dengan mempertimbangkan triple Hoare untuk menampung hanya jika program berakhir dengan benar. Ini adalah pendekatan yang biasa untuk program nonterminating: postcondition berlaku ketika perintah berakhir, yang mungkin tidak selalu terjadi. Jika Anda memperlakukan kesalahan run-time sebagai non-terminasi, Anda menyapu semua masalah kebenaran di bawah tenda. Anda masih perlu membuktikan kebenaran program tersebut, tetapi itu tidak perlu dalam logika Hoare jika Anda lebih suka formalisme lain untuk tugas itu.

By the way, perhatikan bahwa mengekspresikan apa yang terjadi ketika variabel majemuk seperti array diubah lebih terlibat daripada apa yang Anda tulis. Misalkan adalah, katakanlah, : substitusi tidak akan mengubah , namun tugas dapat membatalkan . Bahkan jika Anda membatasi sintaksis predikat hanya untuk berbicara tentang atom, pertimbangkan tugas bawah prasyarat : Anda tidak dapat membuat substitusi sederhana untuk mendapatkan postcondition yang benar , Anda perlu mengevaluasiPIsSorted(A)A[i]EPA[i]PPA[A[0]1]:=A[0]A[0]=2A[1]=3A [ 0 ] A [ 0 ] A A [ i E ]A[0]=1A[1]=1A[0](yang bisa sulit secara umum, karena prasyarat mungkin tidak menentukan nilai tunggal yang mungkin untuk ). Anda perlu melakukan substitusi pada array itu sendiri: . Catatan kuliah Mike Gordon memiliki presentasi logika Hoare yang baik dengan array (tetapi tanpa pengecekan kesalahan).A[0]AA[iE]


0

Seperti yang disebutkan oleh Gilles, ada aksioma penugasan array (lihat catatan Gordon, Bagian 2.1.10 ): Dalam kata-kata, jika Anda memiliki tugas array, maka ganti array asli dengan array yang memiliki posisi nilai . Perhatikan bahwa jika Anda sudah memiliki pada pos, dan menetapkan , maka Anda harus mendapatkan sebagai pra (ya, dalam urutan ini - pembaruan terbaru dijalankan terlebih dahulu!).

{Q[AA.store(i,expr)]}A[i]=expr{Q}
A.store(i,expr)iexprA.store(i,vi)A[j]=vjA.store(j,vj).store(i,vi)

Selain itu, kita perlu aksioma akses array: A.store(i,v)[i]bisa diganti dengan v( "jika Anda mengakses th elemen yang Anda baru saja diperbarui, kemudian kembali nilai yang diberikan").i

Saya pikir untuk membuktikan program dengan array sudah benar ("tidak ada akses yang tidak terbatas"), aksioma di atas sudah cukup. Mari kita perhatikan programnya:

...
A[i] = 12
...

Kami akan membubuhi keterangan program ini:

...
@ {0<i<A_length}
A[i] = 12
...

di mana A_lengthadalah variabel yang menentukan panjang array. Sekarang coba buktikan anotasi - yaitu, kerjakan mundur (dari bawah ke atas, "seperti biasanya" dalam bukti Hoare). Jika di atas Anda dapatkan {false}, maka akses di luar batas dapat terjadi, jika tidak, ekspresi yang Anda dapatkan adalah prasyarat di mana tidak ada akses di luar batas yang dimungkinkan. (juga, kita perlu memastikan bahwa ketika array dibuat seperti int A=int[10];pada post-condition yang kita miliki {A_length==10}).


Aksioma Anda tidak memodelkan akses di luar batas: mereka bahkan tidak menyebutkan panjangnya! Dalam contoh program Anda, bagaimana Anda berhubungan lengthke A?
Gilles 'SANGAT berhenti menjadi jahat'

Benar, aksioma tidak memodelkan akses yang terikat. Pertama, untuk membuktikan suatu program sudah benar, saya menambahkan anotasi yang mengharuskan akses dalam batas. ( lengthBerganti nama A_length.) Kedua, kita perlu berbagai aksioma "penciptaan" seperti int[] a = int[length] {a_length==length}. Saya pikir ini sudah cukup.
Ayrat
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.