(*| ======== Quiz 1 ======== .. raw:: html Grading scheme ============== - +1 for correct answers - -0.5 for incorrect answers .. coq:: none |*) From Stdlib Require Import Bool Arith. Arguments Nat.div: simpl never. (*| Tribools ======== Consider the following definitions: |*) Inductive tribool := yes | no | maybe. Definition And (x y: tribool) : tribool := match x, y with | yes, yes | yes, maybe | maybe, yes => yes | maybe, maybe => maybe | _, _ => no end. Definition Or (x y : tribool) : tribool := match x, y with | yes, _ | _, yes => yes | maybe, _ | _, maybe => maybe | _, _ => no end. Definition Neg (x: tribool): tribool := match x with | yes => no | maybe => maybe | no => yes end. (*| Which of the following properties are true? .. exercise:: `AndIdemp` .. coq:: |*) Property AndIdemp x : And x x = x. (*| :◉: This property holds. :○: This property does not hold. .. solution:: Proof .. coq:: |*) Proof. destruct x; reflexivity. Qed. (*| .. exercise:: `AndDistrOr` .. coq:: |*) Property AndDistrOr x y z : And x (Or y z) = Or (And x y) (And x z). (*| :◉: This property holds. :○: This property does not hold. .. solution:: Proof .. coq:: |*) Proof. destruct x, y, z; reflexivity. Qed. (*| .. exercise:: `NegAndOr` .. coq:: |*) Property NegAndOr x y: Neg (And x y) = Or (Neg x) (Neg y). (*| :○: This property holds. :◉: This property does not hold. .. solution:: Proof .. coq:: |*) Abort. Property NegAndOr: not (forall x y, Neg (And x y) = Or (Neg x) (Neg y)). Proof. intros Heq. specialize Heq with (x := yes) (y := maybe). discriminate Heq. Qed. (*| Soundness and completeness ========================== Consider the following definitions: .. coq:: none |*) Section Defs. Variable prog: Type. Variable safe: prog -> Prop. Variable validate: prog -> bool. (*||*) Definition IfSafeThenValid := forall p, safe p -> validate p = true. (*||*) Definition IfValidThenSafe := forall p, validate p = true -> safe p. (*| .. coq:: none |*) End Defs. (*| .. exercise:: Soundness Which one of these definitions expresses that `validate` is *sound*? :◉: `IfValidThenSafe` :○: `IfSafeThenValid` .. exercise:: Completeness Which one of these definitions expresses that `validate` is *complete*? :○: `IfValidThenSafe` :◉: `IfSafeThenValid` Rejecting the right programs ============================ .. coq:: none |*) Module Soundness. (*| We wish to extend our simple language with an additional constructor for subtraction, `SubThen`. `SubThen n p` subtracts `n` from the state then runs `p`. The semantics of each construct is described in comments: |*) Inductive Prog := | (* Don't modify the state. *) Done | (* Add [n] to the state, then run [p]. *) AddThen (n : nat) (p : Prog) | (* Subtract [n] from the state, then run [p]. *) SubThen (n : nat) (p : Prog) | (* Multiply the state by [n], then run [p]. *) MulThen (n : nat) (p : Prog) | (* Divide the state by [n], then run [p]. *) DivThen (n : nat) (p : Prog) | (* Divide [n] by the state, then run [p]. *) VidThen (n : nat) (p : Prog) | (* Set the state to [n], then run [p]. *) SetToThen (n : nat) (p : Prog). (*| Note that subtraction saturates at 0, i.e. if `n < m`, then `n - m = 0`. We consider the following program-validation function `validate`, intended to reject (return `false` for) every unsafe program. In other words, if `validate` accepts (returns `true` for) `p`, then `p` should be be safe to run with any input (i.e. it will never trigger a division by zero). |*) Fixpoint validate' (p : Prog) (nz : bool) := match p with | Done => true | AddThen 0 p => validate' p nz | AddThen _ p => validate' p true | SubThen _ p => validate' p nz | MulThen 0 p => validate' p false | MulThen _ p => validate' p nz | DivThen 0 _ => false | DivThen 1 p => validate' p nz | DivThen _ p => validate' p false | VidThen _ p => nz && validate' p false | SetToThen 0 p => validate' p false | SetToThen _ p => validate' p true end. Definition validate (p : Prog) : bool := validate' p false. (*| Unsafe programs --------------- .. exercise:: Unsafe and rejected Does `validate` (defined above) return `false` for every unsafe program? :○: Yes :◉: No Unsafe, but accepted :::::::::::::::::::: Which of the following programs are unsafe but accepted by `validate` (defined above), if any? .. coq:: none |*) Fixpoint runPortable (p : Prog) (state : nat) : bool * nat := match p with | Done => (true, state) | AddThen n p => runPortable p (state+n) | SubThen n p => runPortable p (state-n) | MulThen n p => runPortable p (state*n) | DivThen n p => if n =? 0 then (false, state) else runPortable p (state/n) | VidThen n p => if state =? 0 then (false, 0) else runPortable p (n/state) | SetToThen n p => runPortable p n end. (*| .. exercise:: `prog1` .. coq:: |*) Definition prog1 := AddThen 42 (SubThen 42 (VidThen 15 Done)). (*| Is `prog1` unsafe but accepted? :◉: Yes :○: No .. solution:: Proof .. coq:: |*) Goal (fst (runPortable prog1 0), validate prog1) = (false, true). Proof. reflexivity. Qed. (*| .. exercise:: `prog2` .. coq:: |*) Definition prog2 := AddThen 5 (DivThen 2 (SubThen 5 Done)). (*| Is `prog2` unsafe but accepted? :○: Yes :◉: No .. solution:: Proof .. coq:: |*) Goal forall s, fst (runPortable prog2 s) = true. Proof. reflexivity. Qed. (*| .. exercise:: `prog3` .. coq:: |*) Definition prog3 := MulThen 2 (AddThen 4 (SubThen 5 (VidThen 100 Done))). (*| Is `prog3` unsafe but accepted? :◉: Yes :○: No .. solution:: Proof .. coq:: |*) Goal (fst (runPortable prog3 0), validate prog3) = (false, true). Proof. reflexivity. Qed. (*| .. exercise:: `prog4` .. coq:: |*) Definition prog4 := AddThen 0 (SubThen 3 (VidThen 10 Done)). (*| Is `prog4` unsafe but accepted? :○: Yes :◉: No .. solution:: Proof .. coq:: |*) Goal validate prog4 = false. Proof. reflexivity. Qed. (*| Safe programs ------------- .. exercise:: Safe and accepted Does `validate` (defined above) return `true` for every safe program? :○: Yes :◉: No Safe, but rejected :::::::::::::::::: Which of the following programs are safe but rejected by `validate` (defined above), if any? .. exercise:: `prog5` .. coq:: |*) Definition prog5 := AddThen 10 (MulThen 2 (SubThen 5 (VidThen 10 Done))). (*| Is `prog5` safe but rejected? :○: Yes :◉: No .. solution:: Proof .. coq:: |*) Goal validate prog5 = true. Proof. reflexivity. Qed. (*| .. exercise:: `prog6` .. coq:: |*) Definition prog6 := AddThen 40 (DivThen 2 (VidThen 100 Done)). (*| Is `prog6` safe but rejected? :◉: Yes :○: No .. solution:: Proof .. coq:: |*) Goal forall s, (fst (runPortable prog6 s), validate prog6) = (true, false). Proof. simpl; intros. change (s + 40) with (s + 20 * 2). rewrite Nat.div_add, Nat.add_comm by congruence. reflexivity. Qed. (*| .. exercise:: `prog7` .. coq:: |*) Definition prog7 := AddThen 1 (MulThen 40 (DivThen 2 (VidThen 10 Done))). (*| Is `prog7` safe but rejected? :◉: Yes :○: No .. solution:: Proof .. coq:: |*) Goal forall s, (fst (runPortable prog7 s), validate prog7) = (true, false). Proof. simpl; intros. rewrite Nat.Lcm0.divide_div_mul_exact, Nat.add_comm by (exists 20; reflexivity). reflexivity. Qed. (*| .. exercise:: `prog8` .. coq:: |*) Definition prog8 := MulThen 2 (DivThen 1 (VidThen 10 Done)). (*| Is `prog8` safe but rejected? :○: Yes :◉: No .. solution:: Proof .. coq:: |*) Goal fst (runPortable prog8 0) = false. Proof. reflexivity. Qed. (*| .. coq:: none |*) End Soundness.