(*| ======== Quiz 2 ======== .. raw:: html Grading scheme ============== - +1 for correct answers - -0.5 for incorrect answers .. coq:: none |*) From Stdlib Require Import Bool Arith List. Import ListNotations. (*| Binary search trees =================== We define trees as in the lab: |*) Inductive tree := | Leaf | Node (d: nat) (l r: tree). (*| .. coq:: none |*) Fixpoint bst (tr : tree) (s : nat -> Prop) : Prop := match tr with | Leaf => forall x, not (s x) | Node d l r => s d /\ bst l (fun x => s x /\ x < d) /\ bst r (fun x => s x /\ d < x) end. (*| A tree `tr` is a binary search tree if there exists an indicator predicate `s: nat -> Prop` such that `bst tr s` holds (`bst` is as defined in the lab). BST examples ------------ For each example below, indicate whether the tree is a binary search tree: .. exercise:: Singleton Is the following a binary search tree? |*) Definition lf := Leaf. (*| :◉: Yes :○: No .. solution:: Proof .. coq:: |*) Goal bst lf (fun _ => False). Proof. firstorder. Qed. (*| .. exercise:: Left comb Is the following a binary search tree? |*) Definition lcomb := Node 0 Leaf (Node 1 Leaf (Node 2 Leaf Leaf)). (*| :◉: Yes :○: No .. solution:: Proof .. coq:: |*) From Stdlib Require Import Lia. Goal bst lcomb (fun x => 0 <= x <= 2). Proof. cbv; intuition; lia. Qed. (*| .. exercise:: Right comb Is the following a binary search tree? |*) Definition rcomb := Node 0 (Node 1 (Node 2 Leaf Leaf) Leaf) Leaf. (*| :○: Yes :◉: No .. solution:: Proof .. coq:: |*) Goal forall s, ~ bst rcomb s. Proof. cbv; lia. Qed. (*| .. exercise:: Left fold Is the following a binary search tree? |*) Fixpoint fl (l: list nat) (tr: tree) : tree := match l with | [] => tr | hd :: tl => fl tl (Node hd Leaf tr) end. Definition lc := fl [0;1;2;3;4] Leaf. (*| :○: Yes :◉: No .. solution:: Proof .. coq:: |*) Goal forall s, ~ bst lc s. Proof. cbv; lia. Qed. (*| .. exercise:: Right fold Is the following a binary search tree? |*) Fixpoint fr (l: list nat) (tr: tree) : tree := match l with | [] => tr | hd :: tl => Node hd (fr tl tr) Leaf end. Definition rc := fr [0;1;2;3;4] Leaf. (*| :○: Yes :◉: No .. solution:: Proof .. coq:: |*) Goal forall s, ~ bst rc s. Proof. cbv; lia. Qed. (*| BST invariant ------------- There are many ways to define the binary search tree invariant. We say that a candidate definition `is_bst` is *sound* if all trees that satisfy `is_bst` are binary search trees: |*) Definition sound (is_bst: tree -> Prop) := forall tr, is_bst tr -> exists s, bst tr s. (*| We say that a definition `is_bst` is *complete* if all binary search trees satisfy `is_bst`: |*) Definition complete (is_bst: tree -> Prop) := forall tr, (exists s, bst tr s) -> is_bst tr. (*| For each of the following definitions, indicate whether it is sound and whether it is complete. Constants ......... Consider the following definition: |*) Definition is_bst_yes (tr: tree) := True. (*| .. exercise:: Top soundness Is `is_bst_yes` sound? :○: Yes :◉: No .. solution:: Proof .. coq:: |*) Goal ~ sound is_bst_yes. Proof. intros Hs. destruct (Hs (Node 0 (Node 1 Leaf Leaf) Leaf)) as [s Ht]. all: cbv in *; lia. Qed. (*| .. exercise:: Top completeness Is `is_bst_yes` complete? :◉: Yes :○: No .. solution:: Proof .. coq:: |*) Goal complete is_bst_yes. Proof. firstorder. Qed. (*| Consider the following definition: |*) Definition is_bst_no (tr: tree) := False. (*| .. exercise:: Bottom soundness Is `is_bst_no` sound? :◉: Yes :○: No .. solution:: Proof .. coq:: |*) Goal sound is_bst_no. Proof. firstorder. Qed. (*| .. exercise:: Bottom completeness Is `is_bst_no` complete? :○: Yes :◉: No .. solution:: Proof .. coq:: |*) Goal ~ complete is_bst_no. Proof. intros Hs. apply (Hs Leaf). exists (fun _ => False); firstorder. Qed. (*| Fixpoints ......... Consider the following definition: |*) Fixpoint is_bst_fx (tr: tree) := match tr with | Leaf | Node _ Leaf Leaf => True | Node d Leaf r => match r with Leaf => True | Node dr _ _ => d < dr end /\ is_bst_fx r | Node d l Leaf => match l with Leaf => True | Node dl _ _ => dl < d end /\ is_bst_fx l | Node d l r => match r with Leaf => True | Node dr _ _ => d < dr end /\ match l with Leaf => True | Node dl _ _ => dl < d end /\ is_bst_fx l /\ is_bst_fx r end. (*| .. exercise:: Fixpoint soundness Is `is_bst_fx` sound? :○: Yes :◉: No .. solution:: Proof .. coq:: |*) Goal ~ sound is_bst_fx. Proof. intros Hs. destruct (Hs (Node 1 (Node 0 Leaf (Node 2 Leaf Leaf)) Leaf)) as [s Ht]. all: cbv in *; lia. Qed. (*| .. exercise:: Fixpoint completeness Is `is_bst_fx` complete? :◉: Yes :○: No .. solution:: Proof .. coq:: |*) Goal complete is_bst_fx. Proof. unfold complete; induction tr; intros [s Ht]. - reflexivity. - simpl in *. destruct Ht as (Hd & H1 & H2). specialize (IHtr1 ltac:(eauto)). specialize (IHtr2 ltac:(eauto)). destruct tr1, tr2; simpl in *; intuition. Qed. (*| Inductives .......... Consider the following definition: |*) Inductive is_bst_ind' : forall (tr: tree) (s: nat -> Prop), Prop := | is_bst_ind_Leaf s (Hs: forall x, s x <-> False): is_bst_ind' Leaf s | is_bst_ind_Node d l r sl sr s (Hl: is_bst_ind' l sl) (Hr: is_bst_ind' r sr) (Hlt: forall xl, sl xl -> xl < d) (Hgt: forall xr, sr xr -> d < xr) (Hs: forall x, s x <-> x = d \/ sl x \/ sr x): is_bst_ind' (Node d l r) s. Definition is_bst_ind (tr: tree) := exists s, is_bst_ind' tr s. (*| .. exercise:: Inductive soundness Is `is_bst_ind` sound? :◉: Yes :○: No .. solution:: Proof .. coq:: |*) Lemma bst_iff : forall tr s1 s2, (forall x, s1 x <-> s2 x) -> (bst tr s1 <-> bst tr s2). Proof. induction tr; simpl; intros s1 s2 Ht. - firstorder. - rewrite Ht, IHtr1, IHtr2. reflexivity. all: simpl; intros; rewrite Ht; reflexivity. Qed. Lemma is_bst_ind'_sound tr s: is_bst_ind' tr s -> bst tr s. Proof. induction 1; simpl. - firstorder. - rewrite (bst_iff l), (bst_iff r), Hs. + intuition eauto. + firstorder lia. + firstorder lia. Qed. Goal sound is_bst_ind. Proof. intros tr [s Hs%is_bst_ind'_sound]; eauto. Qed. (*| .. exercise:: Inductive completeness Is `is_bst_ind` complete? :◉: Yes :○: No .. solution:: Proof .. coq:: |*) Lemma is_bst_ind'_complete tr: forall s, bst tr s -> is_bst_ind' tr s. Proof. induction tr; simpl. - econstructor; firstorder. - intros s (Hd & H1 & H2). econstructor; eauto; simpl; try lia. intros x; assert (x = d \/ x < d \/ d < x) by lia. intuition (subst; eauto). Qed. Goal complete is_bst_ind. Proof. intros tr [s Hs%is_bst_ind'_complete]; red; eauto. Qed. (*| BST operations .............. Consider the following operation defined on trees: |*) Fixpoint member (a: nat) (tr: tree) : bool := match tr with | Leaf => false | Node v l r => match a ?= v with | Lt => member a l | Gt => member a r | Eq => true end end. (*| For each of the following trees, indicate whether `member 4` returns the correct result (i.e., returns `true` when `4` is in the tree, and `false` when `4` is not in the tree): .. exercise:: `tree1` .. coq:: |*) Definition tree1 := Node 3 (Node 4 Leaf Leaf) (Node 5 (Node 2 Leaf Leaf) Leaf). (*| Does `member 4 tree1` return the right result? :○: Yes :◉: No .. solution:: Proof .. coq:: |*) Goal member 4 tree1 = false. Proof. reflexivity. Qed. (*| .. exercise:: `tree2` .. coq:: |*) Definition tree2 := Node 3 (Node 4 Leaf Leaf) (Node 2 Leaf (Node 4 Leaf Leaf)). (*| Does `member 4 tree2` return the right result? :◉: Yes :○: No .. solution:: Proof .. coq:: |*) Goal member 4 tree2 = true. Proof. reflexivity. Qed. (*| .. exercise:: `tree3` .. coq:: |*) Definition tree3 := Node 3 Leaf (Node 5 Leaf Leaf). (*| Does `member 4 tree3` return the right result? :◉: Yes :○: No .. solution:: Proof .. coq:: |*) Goal member 4 tree3 = false. Proof. reflexivity. Qed.