การพิสูจน์การดำเนินการเรียงลำดับในระบบชนิด


9

ฉันต้องการทราบว่าระบบการพิมพ์ในภาษาการเขียนโปรแกรมมีประโยชน์เพียงใด ตัวอย่างเช่นฉันรู้ว่าในภาษาการเขียนโปรแกรมที่พึ่งพาเราสามารถสร้างVectorคลาสที่รวมขนาดของเวกเตอร์ในลายเซ็นประเภท มันก็เหมือนเป็นตัวอย่างโดยพฤตินัย นอกจากนี้เรายังสามารถเขียนฟังก์ชันappendโดยใช้ลายเซ็นเหล่านั้นเพื่อให้คอมไพเลอร์พิสูจน์ขนาดของรายการผลลัพธ์จะเป็นผลรวมของรายการอินพุต

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

คำตอบ:


13

ใช่เป็นไปได้ที่จะแสดงชนิดที่แม่นยำสำหรับรูทีนการเรียงเช่นฟังก์ชันใด ๆ ที่มีประเภทนั้นจะต้องเรียงลำดับรายการอินพุต

ในขณะที่อาจจะมีวิธีการแก้ปัญหาขั้นสูงและสง่างามกว่าฉันจะวาดภาพระดับประถมศึกษาเท่านั้น

เราจะใช้สัญลักษณ์คล้าย Coq เราเริ่มต้นด้วยการกำหนดคำกริยาที่ต้องf: nat -> natทำหน้าที่เป็นการเปลี่ยนแปลงใน :0..n1

Definition permutation (n: nat) (f: nat -> nat): Prop :=
  (* once restricted, its codomain is 0..n-1 *)
  (forall m, m < n -> f m < n) /\
  (* it is injective, hence surjective *)
  (forall m1 m2, m1 < n -> m2 < n -> f m1 = f m2 -> m1 = m2) .

บทแทรกง่ายสามารถพิสูจน์ได้ง่าย

Lemma lem1: forall n f, permutation n f -> m < n -> f m < n.
... (* from the def *)

เรากำหนดสิ่งที่เป็นองค์ประกอบของความยาวรายการมี TH nฟังก์ชั่นนี้ต้องการหลักฐานที่ระบุว่าอยู่จริงmnhm<n

Definition nth {A} {n} (l: list A n) m (h : m < n): A :=
... (* recursion over n *)

เมื่อได้รับคำสั่งAเราสามารถแสดงรายการที่เรียงลำดับ:

Definition ordering (A: Type) :=
   { leq: A->A->bool |
     (* axioms for ordering *)
     (forall a, leq a a = true) /\
     (forall a b c, leq a b = true -> leq b c = true -> leq a c = true) /\
     (forall a b, leq a b = true -> leq b a = true -> a = b)
    } .

Definition sorted {A} {n} (o: ordering A) (l: list A n): Prop :=
...

ในที่สุดนี่คือประเภทของอัลกอริทึมการเรียงลำดับ:

Definition mysort (A: Type) (o: ordering A) (n: nat) (l: list A n):
   {s: list A n | sorted o s /\
                  exists f (p: permutation n f),
                  forall (m: nat) (h: m < n), 
                     nth l m h = nth s (f m) (lem1 n f p h) } :=
... (* the sorting algorithm, and a certificate for its output *)

รัฐประเภทเอาท์พุทว่ารายการผลที่ได้sคือองค์ประกอบนานก็จะถูกจัดเรียงและที่มีการเปลี่ยนแปลงของที่แมองค์ประกอบในรายการการป้อนข้อมูลกับคนที่อยู่ในรายชื่อที่ส่งออก โปรดทราบว่าเราจะต้องเรียกแทรกด้านบนเพื่อพิสูจน์ซึ่งถูกต้องตามn0..n1lsf(m)<nnth

อย่างไรก็ตามโปรดทราบว่ามันคือผู้ใช้นั่นคือโปรแกรมเมอร์ซึ่งต้องพิสูจน์อัลกอริทึมการเรียงลำดับของพวกเขาให้ถูกต้อง คอมไพเลอร์จะไม่เพียงตรวจสอบว่าการเรียงลำดับนั้นถูกต้อง: ทั้งหมดทำการตรวจสอบหลักฐานที่ให้มา อันที่จริงคอมไพเลอร์ไม่สามารถทำอะไรได้มากกว่านั้น: คุณสมบัติเชิงความหมายเช่น "โปรแกรมนี้เป็นอัลกอริธึมการเรียงลำดับ" ไม่สามารถตัดสินใจได้ (โดยทฤษฎีบทข้าว) ดังนั้นเราจึงไม่สามารถหวังได้ว่าขั้นตอนการพิสูจน์อัตโนมัติ

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

ในฐานะที่เป็นโน้ตสุดท้ายบางครั้งมันก็ถูกลืมว่าแม้ระบบแบบธรรมดาก็ไม่สมบูรณ์ ! เช่นใน Java

int f(int x) {
   if (x+2 != 2+x)
      return "Houston, we have a problem!";
   return 42;
}

ปลอดภัยประเภท semantically (มันมักจะส่งกลับจำนวนเต็ม) แต่ตัวตรวจสอบประเภทจะบ่นเกี่ยวกับผลตอบแทนที่ไม่สามารถเข้าถึงได้


7

Twan van Laarhoven มีตัวอย่างที่สมบูรณ์ใน Agdaของ "ความถูกต้องและการทำงานของการผสานการเรียงลำดับการแทรกและการเรียงลำดับการเลือก"

ความคิดเห็นก็น่าสนใจเช่นกันพวกเขาโซลูชั่นของ Bob Atkey ที่เกี่ยวข้องกับการฝัง Linear Logicเป็นตัวอย่างที่กล่าวถึง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.