A theory of fixed points
Overview
In this document I prove the Knaster-Tarski fixedpoint theorem in a general formulation for HOL.
A new "fixp" theory is created as a child of "hol".
Definition of the notion of a bounded monotonic function and of least and greatest fixed points.
Proofs that "lfp" gives a fixed point and that it is the least fixed point.
Proofs that "gfp" gives a fixed point and that it is the greatest fixed point.
Taking a closure of constructors for an inductive datatype definition.
Introduction
A new "fixp" theory is created as a child of "hol".
The Theory fixp
The new theory is first created, together with a proof context which we will build up as we develop the theory.
xl-sml
open_theory "hol";


xl-sml
force_new_theory "fixp";
force_new_pc "fixp";
merge_pcs ["xl_cs_exist.gif_conv"] "fixp";
set_merge_pcs ["hol", "fixp"];

Definitions
Definition of the notion of a bounded monotonic function and of least and greatest fixed points.
Introduction

monotonic
The property of being a monotonic function.
xl-holconst
monotonic : ('a SET rarr.gif 'b SET) rarr.gif BOOL
forall.giffbull.gif monotonic f equiv.gif forall.gifx ybull.gif x sube.gif y ruarr.gif f(x) sube.gif f(y)

xl-holconst
lfp : ('a SET rarr.gif 'a SET) rarr.gif 'a SET
forall.giffbull.gif lfp f = lcap.gif{X | f X sube.gif X}

xl-holconst
gfp : ('a SET rarr.gif 'a SET) rarr.gif 'a SET
forall.giffbull.gif gfp f = lcup.gif{X | X sube.gif f X}
Least Fixed Points
Proofs that "lfp" gives a fixed point and that it is the least fixed point.
Introduction

lfp Gives Fixed Points

xl-sml
set_goal([],qqtel.gifforall.gifhbull.gif monotonic h ruarr.gif h (lfp h) = lfp hqqter.gif);
a (rewrite_tac [get_spec qqtel.giflfpqqter.gif] THEN REPEAT strip_tac);
a (lemma_tac qqtel.gifh(lcap.gif{X|h X sube.gif X}) sube.gif lcap.gif{X|h X sube.gif X}qqter.gif);
(* *** Goal "1" *** *)
a (once_rewrite_tac[sets_ext_clauses] THEN REPEAT strip_tac);
a (lemma_tac qqtel.gif(lcap.gif{X|h X sube.gif X}) sube.gif sqqter.gif);
(* *** Goal "1.1" *** *)
a (once_rewrite_tac[sets_ext_clauses] THEN REPEAT strip_tac);
a (spec_nth_asm_tac 1 qqtel.gifsqqter.gif);
(* *** Goal "1.2" *** *)
a (all_asm_fc_tac [get_spec qqtel.gifmonotonicqqter.gif]);
a (all_fc_tac[get_spec qqtel.gif$sube.gifqqter.gif]);
a (all_fc_tac[get_spec qqtel.gif$sube.gifqqter.gif]);
(* *** Goal "2" *** *)
a (lemma_tac qqtel.giflcap.gif{X|h X sube.gif X} sube.gif h(lcap.gif{X|h X sube.gif X})qqter.gif);
(* *** Goal "2.1" *** *)
a (once_rewrite_tac[sets_ext_clauses]);
a (REPEAT strip_tac);
a (spec_asm_tac qqtel.gifforall.gif sbull.gif s isin.gif {X|h X sube.gif X} ruarr.gif x isin.gif sqqter.gif qqtel.gifh (lcap.gif {X|h X sube.gif X})qqter.gif);
a (fc_tac [get_spec qqtel.gifmonotonicqqter.gif]);
a (list_spec_asm_tac qqtel.gifforall.gif x ybull.gif x sube.gif y ruarr.gif h x sube.gif h yqqter.gif [qqtel.gifh(lcap.gif {X|h X sube.gif X})qqter.gif, qqtel.giflcap.gif {X|h X sube.gif X}qqter.gif]);
(* *** Goal "2.2" *** *)
a (all_asm_fc_tac [pc_rule "sets_ext" (prove_rule []) qqtel.gifforall.gifA Bbull.gif A sube.gif B and.gif B sube.gif A ruarr.gif A = Bqqter.gif]);
val least_fixpoint_thm = save_pop_thm "least_fixpoint_thm";

lfp Gives the Least Fixed Point

xl-sml
set_goal([],qqtel.gifforall.gifhbull.gif monotonic h ruarr.gif forall.gifgbull.gif h g = g ruarr.gif (lfp h) sube.gif gqqter.gif);
a (rewrite_tac [get_spec qqtel.giflfpqqter.gif] THEN REPEAT strip_tac);
a (once_rewrite_tac [sets_ext_clauses]
fttabTHEN REPEAT strip_tac);
a (spec_asm_tac qqtel.gifforall.gif sbull.gif s isin.gif {X|h X sube.gif X} ruarr.gif x isin.gif sqqter.gif qqtel.gifgqqter.gif);
a (DROP_ASM_T qqtel.gifnot.gif h g sube.gif gqqter.gif ante_tac THEN asm_rewrite_tac []);
val lfp_min_thm = save_pop_thm "lfp_min_thm";

Induction
I'm not whether the following really counts as an induction principle, but I expect it will help in deriving induction principles. It may be read as saying that if the functional preserves some property then that property holds everywhere in the least fixed point.
xl-sml
set_goal([],qqtel.gifforall.gifhbull.gif monotonic h ruarr.gif forall.gifsbull.gif h s sube.gif s ruarr.gif (lfp h) sube.gif sqqter.gif);
a (rewrite_tac [get_spec qqtel.giflfpqqter.gif] THEN REPEAT strip_tac);
a (once_rewrite_tac [sets_ext_clauses] THEN REPEAT strip_tac);
a (asm_fc_tac[]);
val lfp_induction_thm = save_pop_thm "lfp_induction_thm";

Greatest Fixed Points
Proofs that "gfp" gives a fixed point and that it is the greatest fixed point.
Introduction

gfp Gives Fixed Points

xl-sml
set_goal([],qqtel.gifforall.gifhbull.gif monotonic h ruarr.gif h (gfp h) = gfp hqqter.gif);
a (rewrite_tac [get_spec qqtel.gifgfpqqter.gif] THEN REPEAT strip_tac);
a (lemma_tac qqtel.giflcup.gif {X|X sube.gif h X} sube.gif h (lcup.gif {X|X sube.gif h X})qqter.gif);
(* *** Goal "1" *** *)
a (once_rewrite_tac[sets_ext_clauses] THEN REPEAT strip_tac);
a (lemma_tac qqtel.gifs sube.gif lcup.gif {X|X sube.gif h X}qqter.gif);
(* *** Goal "1.1" *** *)
a (once_rewrite_tac[sets_ext_clauses] THEN REPEAT strip_tac);
a (exist.gif_tac qqtel.gifsqqter.gif THEN REPEAT strip_tac);
(* *** Goal "1.2" *** *)
a (lemma_tac qqtel.gifs isin.gif {X|X sube.gif h X}qqter.gif);
(* *** Goal "1.1" *** *)
a (once_rewrite_tac[sets_ext_clauses] THEN REPEAT strip_tac);
a (all_asm_fc_tac [get_spec qqtel.gifmonotonicqqter.gif]);
a (all_asm_fc_tac [get_spec qqtel.gif$sube.gifqqter.gif]);
a (all_asm_fc_tac [get_spec qqtel.gif$sube.gifqqter.gif]);
(* *** Goal "2" *** *)
a (lemma_tac qqtel.gifh (lcup.gif {X|X sube.gif h X}) isin.gif {X|X sube.gif h X}qqter.gif);
(* *** Goal "2.1" *** *)
a (all_asm_fc_tac [get_spec qqtel.gifmonotonicqqter.gif]);
a (asm_rewrite_tac [isin.gif_in_clauses]);
(* *** Goal "2.2" *** *)
a (lemma_tac qqtel.gifh (lcup.gif {X|X sube.gif h X}) sube.gif lcup.gif {X|X sube.gif h X}qqter.gif);
(* *** Goal "2.2.1" *** *)
a (once_rewrite_tac [sets_ext_clauses]);
a (REPEAT strip_tac);
a (exist.gif_tac qqtel.gifh (lcup.gif {X|X sube.gif h X})qqter.gif);
a (REPEAT strip_tac);
(* *** Goal "2.2.2" *** *)
a (rewrite_tac [pc_rule "sets_ext" (prove_rule []) qqtel.gifforall.gifA Bbull.gif A = B equiv.gif B sube.gif A and.gif A sube.gif Bqqter.gif]
fttabTHEN asm_rewrite_tac[]);
val greatest_fixpoint_thm = save_pop_thm "greatest_fixpoint_thm";

gfp Gives the Greatest Fixed Point

xl-sml
set_goal([],qqtel.gifforall.gifhbull.gif monotonic h ruarr.gif forall.gifgbull.gif h g = g ruarr.gif g sube.gif (gfp h)qqter.gif);
a (rewrite_tac [get_spec qqtel.gifgfpqqter.gif] THEN REPEAT strip_tac);
a (once_rewrite_tac [sets_ext_clauses]
fttabTHEN REPEAT strip_tac);
a (exist.gif_tac qqtel.gifgqqter.gif THEN asm_rewrite_tac[]);
val gfp_max_thm = save_pop_thm "gfp_max_thm";

C0-Induction
This is the corresponding theorem for greatest fixed point to the "induction" principle for least fixed points. I don't know whether its any use and am including it for the sake of symmetry!
xl-sml
set_goal([],qqtel.gifforall.gifhbull.gif monotonic h ruarr.gif forall.gifsbull.gif s sube.gif h s ruarr.gif s sube.gif (gfp h)qqter.gif);
a (rewrite_tac [get_spec qqtel.gifgfpqqter.gif] THEN REPEAT strip_tac);
a (once_rewrite_tac [sets_ext_clauses] THEN contr_tac);
a (asm_fc_tac[]);
val gfp_coinduction_thm = save_pop_thm "gfp_coinduction_thm";

Inductive Definitions
Taking a closure of constructors for an inductive datatype definition.
Introduction

The simplest example of interest here is the natural numbers, which can be defined (in HOL) as the smallest set of individuals which includes zero (the individual which is not in the range of the one-one function whose existence is asserted by the usual axiom of infinity) and is closed under the successor function (which is that same one-one function).

We can think of this as forming the natural numbers by starting with some set ({0}) and then adding the additional values following some prescription until no more can be added. Because we are always adding values, the operation on the set-of-values-so-far is monotonic. If the closure is supplied in a suitable manner then a completely general proof of monotonicity will suffice.

There is a little difficulty in doing this automatically because the operators under which closure is wanted (counting the starting points as 0-ary operators) will be of diverse types.

We keep the constructor exactly as it is required on the representation type. This is combined with an "immediate content" function on the domain of the constructor to give a relation which indicates which values are immediate constituents of a constructed value, and then we close up the empty set on the principle of adding a constructed value whenever its immediate constituents are available.

In addition to the constructor function and the content information we want to allow some constraint on values which are acceptable for the construction so that it need not be defined over the entire representation type. In fact this can be coded into the content function by making it reflexive for values which we wish to exclude from the domain. Actually its type doesn't allow reflexive, but mapping these to the universe of the representation type will do the trick.

Monotonicity

The following function converts such a relationship into a monotonic function. The initial "cc" in the name stands for "constructor and content (functions)".


xl-holconst
fttabcc2monof: ('a rarr.gif 'b) cross.gif ('a rarr.gif 'b SET) rarr.gif ('b SET rarr.gif 'b SET)
fttabforall.giftor tentbull.gif cc2monof (tor, tent) = lambda.gifsbull.gif s cup.gif {t | exist.gifu vbull.gif u = tent v and.gif u sube.gif s and.gif t = tor v}
We prove that this is the case:
xl-sml
set_goal([], qqtel.gifforall.giftor tentbull.gif monotonic (cc2monof (tor, tent))qqter.gif);
a (rewrite_tac [get_spec qqtel.gifcc2monofqqter.gif] THEN REPEAT strip_tac);
a (rewrite_tac [get_spec qqtel.gifmonotonicqqter.gif]);
a (once_rewrite_tac [sets_ext_clauses] THEN REPEAT strip_tac);
(* *** Goal "1" *** *)
a (asm_fc_tac[]);
(* *** Goal "2" *** *)
a (exist.gif_tac qqtel.gifuqqter.gif);
a (exist.gif_tac qqtel.gifvqqter.gif THEN REPEAT strip_tac);
a (DROP_ASM_T qqtel.gifu sube.gif xqqter.gif ante_tac
fttabTHEN DROP_ASM_T qqtel.gifforall.gif x'bull.gif x' isin.gif x ruarr.gif x' isin.gif yqqter.gif ante_tac
fttabTHEN PC_T1 "sets_ext" prove_tac []);
val mono_cc2monof_thm = save_pop_thm "mono_cc2monof_thm";

Closure
The following function defines the least fixed point of such an operator:
xl-holconst
fttabclosure: ('a rarr.gif 'b) cross.gif ('a rarr.gif 'b SET) rarr.gif 'b SET
fttabforall.giftor tentbull.gif closure (tor, tent) = lfp (cc2monof (tor, tent))
We now prove that the result is indeed closed under the operations:
xl-sml
set_goal([], qqtel.gifforall.giftor tent s x ybull.gif
fttab tent x = s
fttaband.gif s sube.gif (closure (tor, tent))
fttaband.gif y = tor x
fttabruarr.gif y isin.gif (closure (tor, tent))qqter.gif);
a (rewrite_tac [get_spec qqtel.gifclosureqqter.gif] THEN REPEAT strip_tac);
a (asm_tac (list_forall.gif_elim [qqtel.giftorqqter.gif, qqtel.giftentqqter.gif] mono_cc2monof_thm));
a (ALL_FC_T (once_rewrite_tac o (map eq_sym_rule)) [least_fixpoint_thm]);
a (rewrite_tac[get_spec qqtel.gifcc2monofqqter.gif]
fttabTHEN REPEAT strip_tac);
a (exist.gif_tac qqtel.gifsqqter.gif THEN asm_rewrite_tac[]);
a (exist.gif_tac qqtel.gifxqqter.gif THEN asm_rewrite_tac[]);
a (DROP_ASM_T qqtel.gifs sube.gif lfp (cc2monof (tor, tent))qqter.gif ante_tac
fttabTHEN rewrite_tac[get_spec qqtel.gifcc2monofqqter.gif]);
val closure_thm1 = save_pop_thm "closure_thm1";

Induction
We prove an induction theorem for sets defined as closures.
xl-sml
set_goal([], qqtel.gifforall.giftor tent pbull.gif
fttab(forall.gifxbull.gif (exist.gifybull.gif tor y = x and.gif tent y sube.gif p) ruarr.gif x isin.gif p)
fttabruarr.gif closure (tor, tent) sube.gif pqqter.gif);
a (rewrite_tac [get_spec qqtel.gifclosureqqter.gif]);
a (REPEAT strip_tac);
a (asm_tac (list_forall.gif_elim [qqtel.giftorqqter.gif, qqtel.giftentqqter.gif] mono_cc2monof_thm));
a (fc_tac [lfp_induction_thm]);
a (spec_asm_tac qqtel.gifforall.gif sbull.gif cc2monof (tor, tent) s sube.gif s ruarr.gif lfp (cc2monof (tor, tent)) sube.gif sqqter.gif qqtel.gifpqqter.gif);
a (swap_asm_concl_tac qqtel.gifnot.gif cc2monof (tor, tent) p sube.gif pqqter.gif);
a (rewrite_tac [get_spec qqtel.gifcc2monofqqter.gif]);
a (once_rewrite_tac [sets_ext_clauses]);
a (REPEAT strip_tac);
a (spec_asm_tac qqtel.gifforall.gif xbull.gif (exist.gif ybull.gif tor y = x and.gif tent y sube.gif p) ruarr.gif x isin.gif pqqter.gif qqtel.gifxqqter.gif);
a (spec_asm_tac qqtel.gifforall.gif ybull.gif not.gif (tor y = x and.gif tent y sube.gif p)qqter.gif qqtel.gifvqqter.gif);
(* *** Goal "1" *** *)
a (DROP_ASM_T qqtel.gifnot.gif tor v = xqqter.gif ante_tac
fttabTHEN asm_rewrite_tac[]);
(* *** Goal "2" *** *)
a (DROP_ASM_T qqtel.gifu sube.gif pqqter.gif ante_tac
fttabTHEN once_asm_rewrite_tac[]
fttabTHEN strip_tac);
val closure_induction_thm = save_pop_thm "closure_induction_thm";

Coding Constructors
Definitions of constructors for products and lists, and injections for disjoint unions.
Definitions
In the following constructor definitions the first argument is expected to be an injection from a preferred indexing type for this constructor to some actual indexing type.
xl-holconst
IndPair : (BOOL rarr.gif 'a) rarr.gif ('a LIST rarr.gif (ONE + 'b)) cross.gif ('a LIST rarr.gif (ONE + 'b))
fttabrarr.gif ('a LIST rarr.gif (ONE + 'b))
forall.gifi l r h tbull.gif
fttabIndPair i (l, r) Nil = InL One
and.giffttabIndPair i (l, r) (Cons h t) =
fttabfttabif h = i F then l t
fttabfttabelse if h = i T then r t
fttabfttabelse InL One

xl-holconst
IndInL : (BOOL rarr.gif 'a) rarr.gif ('a LIST rarr.gif (ONE + 'b))
fttabrarr.gif ('a LIST rarr.gif (ONE + 'b))
forall.gifi j h tbull.gif
fttabIndInL i j Nil = InL One
and.giffttabIndInL i j (Cons h t) =
fttabfttabif h = i F then j t
fttabfttabelse InL One

xl-holconst
IndInR : (BOOL rarr.gif 'a) rarr.gif ('a LIST rarr.gif (ONE + 'b))
fttabrarr.gif ('a LIST rarr.gif (ONE + 'b))
forall.gifi j h tbull.gif
fttabIndInR i j Nil = InL One
and.giffttabIndInR i j (Cons h t) =
fttabfttabif h = i T then j t
fttabfttabelse InL One

xl-holconst
IndSum : (BOOL rarr.gif 'a) rarr.gif ('a LIST rarr.gif (ONE + 'b)) + ('a LIST rarr.gif (ONE + 'b))
fttabrarr.gif ('a LIST rarr.gif (ONE + 'b))
forall.gifi j h tbull.gif
fttab(IndSum i j Nil = InL One)
and.giffttab(IndSum i j (Cons h t) =
fttabfttabif IsL j
fttabfttabthenfttabif h = i F
fttabfttabfttabthen OutL j t
fttabfttabfttabelse InL One
fttabfttabelsefttabif h = i T
fttabfttabfttabthen OutR j t
fttabfttabfttabelse InL One)

xl-holconst
IndList : (nat.gif rarr.gif 'a) rarr.gif ('a LIST rarr.gif (ONE + 'b)) LIST
fttabrarr.gif ('a LIST rarr.gif (ONE + 'b))
forall.gifi ha ta hb tbbull.gif
fttabIndList i Nil tb = InL One
and.giffttabIndList i (Cons ha ta) Nil = InL One
and.giffttabIndList i (Cons ha ta) (Cons hb tb) =
fttabfttabif (exist.gifjbull.gif hb = i j and.gif j < Length ta) then IndList i ta (Cons hb tb)
fttabfttabelse if hb = i (Length ta) then (ha tb)
fttabfttabelse InL One
Computing a Constructor
The following function takes a HOL type and a list of constructors and computes a compound constructor. The HOL type should have a sum of any finite number of distinct type variables as its codomain The constructors should include one for each type constructor which is involved in the recursion.
Computing a Constructor
Proof Context
In this section I will create a decent proof context for fixedpoints, eventually.
Proof Context

xl-sml
commit_pc "fixp";


up quick index © RBJ

$Id: x001.xml,v 1.5 2008/04/15 18:21:36 rbj01 Exp $

V