[Coq] well-founded relation

前回のエントリと同じ気持ちを,
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.

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*