src/HOL/Lfp.ML
author nipkow
Tue, 09 May 1995 22:10:08 +0200
changeset 1114 c8dfb56a7e95
parent 923 ff1574a81019
child 1125 13a3df2adbe5
permissions -rw-r--r--
Prod is now a parent of Lfp. Added thm induct2 to Lfp. Changed the way patterns in abstractions are pretty printed. It has become simpler now but fails if split has more than one argument because then the ast-translation does not match.

(*  Title: 	HOL/lfp.ML
    ID:         $Id$
    Author: 	Lawrence C Paulson, Cambridge University Computer Laboratory
    Copyright   1992  University of Cambridge

For lfp.thy.  The Knaster-Tarski Theorem
*)

open Lfp;

(*** Proof of Knaster-Tarski Theorem ***)

(* lfp(f) is the greatest lower bound of {u. f(u) <= u} *)

val prems = goalw Lfp.thy [lfp_def] "[| f(A) <= A |] ==> lfp(f) <= A";
by (rtac (CollectI RS Inter_lower) 1);
by (resolve_tac prems 1);
qed "lfp_lowerbound";

val prems = goalw Lfp.thy [lfp_def]
    "[| !!u. f(u) <= u ==> A<=u |] ==> A <= lfp(f)";
by (REPEAT (ares_tac ([Inter_greatest]@prems) 1));
by (etac CollectD 1);
qed "lfp_greatest";

val [mono] = goal Lfp.thy "mono(f) ==> f(lfp(f)) <= lfp(f)";
by (EVERY1 [rtac lfp_greatest, rtac subset_trans,
	    rtac (mono RS monoD), rtac lfp_lowerbound, atac, atac]);
qed "lfp_lemma2";

val [mono] = goal Lfp.thy "mono(f) ==> lfp(f) <= f(lfp(f))";
by (EVERY1 [rtac lfp_lowerbound, rtac (mono RS monoD), 
	    rtac lfp_lemma2, rtac mono]);
qed "lfp_lemma3";

val [mono] = goal Lfp.thy "mono(f) ==> lfp(f) = f(lfp(f))";
by (REPEAT (resolve_tac [equalityI,lfp_lemma2,lfp_lemma3,mono] 1));
qed "lfp_Tarski";


(*** General induction rule for least fixed points ***)

val [lfp,mono,indhyp] = goal Lfp.thy
    "[| a: lfp(f);  mono(f);  				\
\       !!x. [| x: f(lfp(f) Int {x.P(x)}) |] ==> P(x) 	\
\    |] ==> P(a)";
by (res_inst_tac [("a","a")] (Int_lower2 RS subsetD RS CollectD) 1);
by (rtac (lfp RSN (2, lfp_lowerbound RS subsetD)) 1);
by (EVERY1 [rtac Int_greatest, rtac subset_trans, 
	    rtac (Int_lower1 RS (mono RS monoD)),
	    rtac (mono RS lfp_lemma2),
	    rtac (CollectI RS subsetI), rtac indhyp, atac]);
qed "induct";

val major::prems = goal Lfp.thy
  "[| (a,b) : lfp f; mono f; \
\     !!a b. (a,b) : f(lfp f Int Collect(split P)) ==> P a b |] ==> P a b";
by(res_inst_tac [("c1","P")] (split RS subst) 1);
br (major RS induct) 1;
brs prems 1;
by(res_inst_tac[("p","x")]PairE 1);
by(hyp_subst_tac 1);
by(asm_simp_tac (prod_ss addsimps prems) 1);
qed"induct2";

(** Definition forms of lfp_Tarski and induct, to control unfolding **)

val [rew,mono] = goal Lfp.thy "[| h==lfp(f);  mono(f) |] ==> h = f(h)";
by (rewtac rew);
by (rtac (mono RS lfp_Tarski) 1);
qed "def_lfp_Tarski";

val rew::prems = goal Lfp.thy
    "[| A == lfp(f);  mono(f);   a:A;  			\
\       !!x. [| x: f(A Int {x.P(x)}) |] ==> P(x) 	\
\    |] ==> P(a)";
by (EVERY1 [rtac induct,	(*backtracking to force correct induction*)
	    REPEAT1 o (ares_tac (map (rewrite_rule [rew]) prems))]);
qed "def_induct";

(*Monotonicity of lfp!*)
val [prem] = goal Lfp.thy "[| !!Z. f(Z)<=g(Z) |] ==> lfp(f) <= lfp(g)";
br (lfp_lowerbound RS lfp_greatest) 1;
be (prem RS subset_trans) 1;
qed "lfp_mono";