前回のエントリと同じ気持ちを,
list を使って書いてみる.
Inductive tree : Type := | node : nat -> list tree -> tree.
今回も,Coqが生成する tree_ind は役に立たない.
forall P : tree -> Prop, (forall (n : nat) (l : list tree), P (node n l)) -> forall t : tree, P t
そこで,「t1はt2の子ノード」という有基底的関係 child(t1, t2)
に関する帰納法を使ってみることにする.
Inductive child (t: tree) : tree -> Prop := | child_w: forall n l, In t l -> child t (node n l).
使うためには,child が well_founded であることを証明する
必要がある.現状,この証明が汚い (下のソースを参照).
Lemma child_well_founded: well_founded child.
ここで,well_founded (など) は,以下のように定義されている.
Inductive Acc (A : Type) (R : A -> A -> Prop) (x : A) : Prop := Acc_intro : (forall y : A, R y x -> Acc R y) -> Acc R x well_founded = fun (A : Type) (R : A -> A -> Prop) => forall a : A, Acc R a : forall A : Type, (A -> A -> Prop) -> Prop
これができると,次のように帰納法を使うことができる.
induction t using (well_founded_ind child_well_founded).
もっと簡単な書き方があるのかもしれないが,一応これで
動いている.
ちなみに,well_founded_ind child_well_founded は,以下の
型を持つ:
forall P : tree -> Prop, (forall x : tree, (forall y : tree, child y x -> P y) -> P x) -> forall a : tree, P a
ソース全体は以下の通り
Require Import List. Require Import Arith. Inductive tree : Type := | node : nat -> list tree -> tree. Definition multi_max (l:list nat) : nat := fold_left (fun x y => if (le_lt_dec x y) then y else x) l 0. Definition total (l:list nat) : nat := fold_left (fun x y => x + y) l 0. Fixpoint height (t: tree) : nat := match t with | node a l => (multi_max (map height l)) + 1 end. Fixpoint numnodes (t: tree) : nat := match t with | node a l => (total (map numnodes l)) + 1 end. (* "child t1 t2" means t1 is a child of t2 *) Inductive child (t: tree) : tree -> Prop := | child_w: forall n l, In t l -> child t (node n l). Search ((_ < S _) -> _ ) . Lemma lt_n_Sm_lt_or_eq: forall n m : nat, n < S m -> n < m \/ n = m. Proof. admit. Qed. Lemma in_le_total: forall a l, In a l -> a <= total l. Proof. admit. Qed. Lemma plus_S_lt: forall x y z, x + S y = z -> x < z. Proof. admit. Qed. Lemma child_acc_n : forall n t, numnodes t < n -> Acc child t. Proof. induction n; intros. inversion H. apply lt_n_Sm_lt_or_eq in H. destruct H. apply IHn; auto. destruct t. apply Acc_intro; intros. apply IHn. simpl in H. assert (In (numnodes y) (map numnodes l)). apply in_map. inversion H0; auto. apply in_le_total in H1. apply plus_S_lt in H. eapply le_lt_trans; [apply H1|]. trivial. Qed. Lemma child_well_founded: well_founded child. Proof. unfold well_founded. intros. apply child_acc_n with (n:=S (numnodes a)). apply le_lt_n_Sm. apply le_refl. Qed. Lemma plus_monotone: forall x1 y1 x2 y2, x1 <= x2 -> y1 <= y2 -> x1 + y1 <= x2 + y2. Proof. admit. Qed. Lemma plus_left_monotone: forall x y z, x <= y -> x + z <= y + z. Proof. admit. Qed. Lemma multi_max_cons x l: multi_max (x::l) = max x (multi_max l). Proof. admit. Qed. Lemma total_cons x l: total (x::l) = x + total l. Proof. admit. Qed. Lemma max_le_plus: forall x y, max x y <= x + y. Proof. admit. Qed. Lemma lem1: forall t, height t <= numnodes t. Proof. induction t using (well_founded_ind child_well_founded). destruct t; simpl; auto. apply plus_left_monotone. generalize l H; clear l H. induction l; intros; simpl; auto. rewrite multi_max_cons, total_cons. eapply le_trans. apply max_le_plus. apply plus_monotone. apply H. apply child_w. simpl; auto. apply IHl. intros; apply H. apply child_w. right. inversion H0; auto. Qed.