Tree.v (90 lines of code) (raw):

Require Import Commons. (* Definition of Tree as ssreflect eqType *) Section TreeDef. Unset Elimination Schemes. Inductive tree (T : Type) : Type := Node of T & seq (tree T). Global Arguments Node [T]. Context {T : Type}. Definition value (t : tree T) := match t with | Node v _ => v end. Definition children (t : tree T) := match t with | Node _ cs => cs end. Definition NodeW (t : T) (ls : option (seq (tree T))) := match ls with Some l' => Some (Node t l') | _ => None end. Lemma nodew_none x xs: NodeW x xs = None <-> xs = None. Proof. split; by [case: xs => [xs|]|move=> ->]. Qed. Lemma nodew_some x ls x2 ls2: NodeW x ls = Some (Node x2 ls2) <-> (x = x2 /\ ls = Some ls2). Proof. by split; [case : ls => [ls|] //=|]; move=> [] -> ->. Qed. Lemma nodew_someS x ls x2 ls2: Some (Node x2 ls2) = NodeW x ls <-> (x = x2 /\ ls = Some ls2). Proof. by split; [case : ls => [ls|] //=|]; move=> [] -> ->. Qed. Definition tree_rect (K : tree T -> Type) (IH_leaf : forall (x : T), K (Node x nil)) (IH_node : forall (x : T) (x0 : seq (tree T)), foldr (fun t : tree T => prod (K t)) unit x0 -> K (Node x x0)) : (forall s : tree T, K s) := fix loop t : K t := match t with Node x nil => IH_leaf x | Node x f0 => let fix iter_pair f : foldr (fun t => prod (K t)) unit f := if f is t :: f' then (loop t, iter_pair f') else tt in IH_node x f0 (iter_pair f0) end. Definition tree_rec (K : tree T -> Set) := tree_rect K. Definition tree_ind (K : tree T -> Prop) (IH_leaf : (forall (x : T), K (Node x nil))) (IH_node : (forall (x : T) (x0 : seq (tree T)), foldr (fun t : tree T => and (K t)) True x0 -> K (Node x x0))) : (forall (s : tree T), K s) := fix loop t : K t : Prop := match t with | Node x nil => IH_leaf x | Node x f0 => let fix iter_conj f : foldr (fun t => and (K t)) True f := if f is t :: f' then conj (loop t) (iter_conj f') else Logic.I in IH_node x f0 (iter_conj f0) end. Fixpoint encode (t : tree T) : seq (option T) := match t with Node x f => (Some x) :: rcons (flatten (map encode f)) (None) end. Definition decode_step (c : option T) (fs : (seq (tree T)) * seq (seq (tree T))) := match c with Some x => (Node x fs.1 :: head [::] fs.2, behead fs.2) | _ => ([::], fs.1 :: fs.2) end. Definition decode c := ohead (foldr decode_step ([::], [::]) c).1. Lemma codeK : pcancel encode decode. Proof. move=> t; rewrite /decode; set fs := (_, _). suffices ->: foldr decode_step fs (encode t) = (t :: fs.1, fs.2) by []. elim: t => //= n f IHt in (fs) *; elim: f IHt => //= t f IHf []. by rewrite rcons_cat foldr_cat => -> /= /IHf[-> -> ->]. Qed. Section Weight. Definition weight (t : tree T) : nat := foldr addn 0 (map (fun o => match o with Some _ => 1 | _ => 0 end) (encode t)). Definition weights (c : seq (tree T)) := foldr addn 0 (map weight c). Lemma weight_Node c ch: weight (Node c ch) = weights ch + 1. rewrite /weight /= map_rcons /weights -cats1 foldr_cat /= /weight. elim: ch => [|a l] //=. rewrite map_cat foldr_cat /= addn0. rewrite (faddr (foldr addn 0 _)) ?addn1 ?add1n /=. remember (foldr addn 0 (map _ (encode a))) as h1. by rewrite (addnC h1) -?addSn => ->. Qed. Lemma weights_cons (a : tree T) l: weights (a :: l) = weight a + weights l. by rewrite /weights /=. Qed. Lemma weights_app (l1 l2 : seq (tree T)): weights (l1 ++ l2) = weights l1 + weights l2. elim: l1 => [|a l1] //=; by rewrite ?weights_cons -addnA => ->. Qed. Lemma weights_drop: forall n (l : seq (tree T)), weights (drop n l) <= weights l. elim => [|n IHn] [|a l] //=. rewrite weights_cons. move: (IHn l). rewrite -ltnS -(ltnS _ (addn _ _)) -addnS. by apply /ltn_addl. Qed. Lemma weights_take: forall n (l : seq (tree T)), weights (take n l) <= weights l. elim => [|n IHn] [|a l] //=. rewrite weights_cons. move: (IHn l). by rewrite weights_cons leq_add2l. Qed. Lemma weights_rot: forall n (l : seq (tree T)), weights (rot n l) = weights l. elim => [|n IHn] [|a l] //=; try by rewrite rot0. move: (IHn l). rewrite /rot. by rewrite drop_cons take_cons ?weights_app ?weights_cons addnA (addnC _ (weight _)) -?addnA => <-. Qed. Corollary weights_rotr n (l : seq (tree T)): weights (rotr n l) = weights l. by rewrite /rotr weights_rot. Qed. End Weight. End TreeDef. Definition tree_eqMixin (T : eqType) := PcanEqMixin (@codeK T). Canonical tree_eqType (T : eqType) := @EqType (tree T) (tree_eqMixin T). Check @Node. Lemma tree_eqP (T : eqType) (t1 t2 : T) l1 l2: Node t1 l1 == Node t2 l2 <-> (t1 = t2) /\ (l1 = l2). split. by move /eqP => [] -> ->. by case => -> ->. Qed. Lemma Node_eq (T : eqType) (x : T) lx y ly: ((Node x lx) == (Node y ly)) = (x == y) && (lx == ly). case: (@eqP _ (Node x lx) (Node y ly)) => [[-> ->]| A0]. by rewrite ?eq_refl. by case: andP A0 => // [] [] /eqP -> /eqP ->. Qed.