วิธีจัดการกับอาร์เรย์ในระหว่างการพิสูจน์ความถูกต้องของ Hoare-style


11

ในการอภิปรายคำถามนี้ Gilles กล่าวอย่างถูกต้องว่าการพิสูจน์ความถูกต้องใด ๆ ของอัลกอริทึมที่ใช้อาร์เรย์ต้องพิสูจน์ว่าไม่มีการเข้าถึงอาร์เรย์นอกขอบเขต ขึ้นอยู่กับรุ่นรันไทม์สิ่งนี้จะทำให้เกิดข้อผิดพลาดรันไทม์หรือการเข้าถึงองค์ประกอบที่ไม่ใช่อาร์เรย์

เทคนิคหนึ่งที่พบบ่อยในการดำเนินการพิสูจน์ความถูกต้องเช่น (อย่างน้อยในการศึกษาปริญญาตรีและอาจจะอยู่ในการตรวจสอบโดยอัตโนมัติ) โดยใช้ตรรกะโฮร์ ฉันไม่ทราบว่าชุดกฎมาตรฐานมีอะไรที่เกี่ยวข้องกับอาร์เรย์ ดูเหมือนว่าพวกเขาจะถูก จำกัด ให้ตัวแปรตัวแปร

ฉันจินตนาการถึงการเพิ่มสัจพจน์ของแบบฟอร์ม

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

แต่ก็ไม่เป็นที่ชัดเจนกับผมว่าคุณจะจัดการกับการเข้าถึงอาร์เรย์บนด้านขวามือคือถ้ามันเป็นส่วนหนึ่งของการแสดงออกที่ซับซ้อนในบางคำสั่งx : = EEx:=E

วิธีการเข้าถึงอาร์เรย์สามารถสร้างแบบจำลองในตรรกะของ Hoare เพื่อให้ไม่มีการเข้าถึงที่ไม่ถูกต้องสามารถและต้องได้รับการพิสูจน์ความถูกต้องของโปรแกรม?

รู้รอบอาจสันนิษฐานได้ว่าเราไม่อนุญาตให้ใช้องค์ประกอบของอาร์เรย์ในงบนอกเหนือจากหรือเป็นส่วนหนึ่งของEบางตัวในx : = Eเนื่องจากไม่ได้ จำกัด การแสดงออก เราสามารถกำหนดตัวแปรชั่วคราวตามค่าที่ต้องการเช่น write t : = A [ i ] ; ฉันf ( t > 0 ) แทนที่จะเป็นฉันf ( A [ i ] > 0 ) ...A[i]:=EEx:=Et:=A[i]; if(t>0)if(A[i]>0).

คำตอบ:


8

{P}C{P}PPCCCสอดคล้องกับไวยากรณ์ที่ไม่มีบริบทและอาจเป็นไปได้ว่าตัวแปรอิสระอยู่ภายในชุดที่ได้รับอนุญาต หากภาษามีโครงสร้างที่มีความถูกต้องทางความหมายเช่นการเข้าถึงองค์ประกอบของแถวลำดับคุณต้องเพิ่มสมมติฐานเพื่อแสดงความถูกต้องทางความหมายนี้

{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}

errorerrorError¬Error

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

อีกวิธีหนึ่งคือการพิจารณา Hoare triple ให้ถือเฉพาะเมื่อโปรแกรมสิ้นสุดอย่างถูกต้อง นี่เป็นวิธีปกติสำหรับโปรแกรมที่ไม่ทำการทำลาย: postcondition เก็บไว้เมื่อคำสั่งถูกยกเลิกซึ่งอาจไม่เกิดขึ้นเสมอไป หากคุณถือว่าข้อผิดพลาดรันไทม์เป็นแบบไม่สิ้นสุดคุณจะกวาดล้างปัญหาความถูกต้องทั้งหมดภายใต้ประทุน คุณจะต้องพิสูจน์ความถูกต้องของโปรแกรม แต่อย่างใด แต่มันไม่จำเป็นต้องอยู่ในตรรกะของ Hoare หากคุณต้องการความเป็นระเบียบแบบอื่นสำหรับงานนั้น

โปรดทราบว่าการแสดงสิ่งที่เกิดขึ้นเมื่อมีการแก้ไขตัวแปรแบบผสมเช่นอาเรย์นั้นเกี่ยวข้องกับสิ่งที่คุณเขียนมากขึ้น สมมติว่าคือพูด : การแทนที่จะไม่เปลี่ยนแต่การมอบหมายอาจทำให้ผิดพลาดได้ แม้ว่าคุณจะ จำกัด ไวยากรณ์ของเพรดิเคตที่จะพูดถึงอะตอมเท่านั้นให้พิจารณาการมอบหมายภายใต้เงื่อนไข : คุณไม่สามารถทำการทดแทนอย่างง่าย ๆ เพื่อรับ postcondition ที่ถูกต้องคุณต้องประเมินPIsSorted(A)A[i]EPA[i]PPA[A[0]1]:=A[0]A[0]=2A[1]=3A[0]=1A[1]=1A[0](ซึ่งอาจเป็นเรื่องยากโดยทั่วไปเนื่องจากเงื่อนไขอาจไม่ระบุค่าที่เป็นไปได้เดียวสำหรับ ) คุณจำเป็นต้องดำเนินการเปลี่ยนตัวในอาร์เรย์ตัวเอง:E] บันทึกการบรรยายของ Mike Gordonมีตรรกะการนำเสนอที่ดี Hoare พร้อมอาร์เรย์ (แต่ไม่มีการตรวจสอบข้อผิดพลาด)A[0]AA[iE]


0

ดังที่ Gilles กล่าวไว้มีสัจพจน์การมอบหมายอาเรย์ (ดูบันทึกของ Gordon, Sec. 2.1.10 ): ในคำถ้าคุณมีการกำหนดอาร์เรย์แล้วแทนที่อาร์เรย์ต้นฉบับโดยอาร์เรย์ซึ่งมีที่ตำแหน่งค่า โปรดทราบว่าหากคุณมีโพสต์และมอบหมายแล้วคุณควรจะได้รับก่อน (ใช่ในลำดับนี้ - การอัปเดตล่าสุดจะถูกดำเนินการก่อน!)

{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)

นอกจากนี้เราต้องการอาเรย์การเข้าถึงอาเรย์: A.store(i,v)[i]สามารถถูกแทนที่ด้วยv("ถ้าคุณเข้าถึงองค์ประกอบที่ที่คุณเพิ่งปรับปรุงแล้วส่งกลับค่าที่กำหนด")i

ฉันคิดว่าเพื่อพิสูจน์ว่าโปรแกรมที่มีอาร์เรย์นั้นถูกต้อง ("ไม่มีการเข้าถึงนอกขอบเขต") สัจพจน์ข้างต้นก็เพียงพอแล้ว ลองพิจารณาโปรแกรม:

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

เราจะใส่คำอธิบายประกอบโปรแกรมนี้:

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

โดยที่A_lengthเป็นตัวแปรที่ระบุความยาวของอาร์เรย์ ตอนนี้พยายามพิสูจน์คำอธิบายประกอบ - กล่าวคือทำงานย้อนหลัง (จากล่างขึ้นบน "มักจะเป็น" ในการพิสูจน์ Hoare) ถ้าคุณอยู่ด้านบนสุด{false}การเข้าถึงที่ไม่อยู่ในขอบเขตสามารถเกิดขึ้นได้มิฉะนั้นนิพจน์ที่คุณได้รับคือเงื่อนไขที่ไม่สามารถเข้าถึงนอกขอบเขตได้ (นอกจากนี้เราต้องตรวจสอบให้แน่ใจว่าเมื่อสร้างอาร์เรย์เช่นint A=int[10];นั้นในโพสต์เงื่อนไขที่เรามี{A_length==10})


สัจพจน์ของคุณไม่ได้จำลองขอบเขตการเข้าถึง: พวกเขาไม่ได้พูดถึงความยาว! ในโปรแกรมตัวอย่างของคุณคุณจะทำอย่างไรที่เกี่ยวข้องlengthเพื่อA?
Gilles 'หยุดความชั่วร้าย'

ขวาสัจพจน์ไม่ได้โมเดลออกจากการเข้าถึงที่ถูกผูกไว้ ก่อนอื่นเพื่อพิสูจน์ว่าโปรแกรมนั้นถูกต้องฉันจะเพิ่มคำอธิบายประกอบที่ต้องการการเข้าถึงที่อยู่ภายในขอบเขต ( lengthเปลี่ยนชื่อเป็นA_length.) ประการที่สองเราต้องอาร์เรย์ "สร้าง" int[] a = int[length] {a_length==length}หลักการเช่น ฉันคิดว่านี่น่าจะเพียงพอแล้ว
Ayrat
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.