header {* \isaheader{Generic Recursion Combinator for Complete Lattice Structured Domains} *}
theory RefineG_Recursion
imports "../Refine_Misc" RefineG_Transfer RefineG_Domain
begin
text {*
We define a recursion combinator that asserts monotonicity.
*}
text {*
The following lemma allows to compare least fixed points wrt.\ different flat
orderings. At any point, the fixed points are either equal or have their
orderings bottom values.
*}
lemma fp_compare:
-- {*At any point, fixed points wrt.\ different orderings are either equal,
or both bottom.*}
assumes M1: "flatf_mono b1 B" and M2: "flatf_mono b2 B"
shows "flatf_fp b1 B x = flatf_fp b2 B x
∨ (flatf_fp b1 B x = b1 ∧ flatf_fp b2 B x = b2)"
proof -
note UNF1 = flatf_ord.fixp_unfold[OF M1, symmetric]
note UNF2 = flatf_ord.fixp_unfold[OF M2, symmetric]
from UNF1 have 1: "flatf_ord b2 (B (flatf_fp b1 B)) (flatf_fp b1 B)" by simp
from UNF2 have 2: "flatf_ord b1 (B (flatf_fp b2 B)) (flatf_fp b2 B)" by simp
from flatf_ord.fixp_lowerbound[OF M2 1] flatf_ord.fixp_lowerbound[OF M1 2]
show ?thesis unfolding fun_ord_def flat_ord_def by auto
qed
lemma flat_ord_top[simp]: "flat_ord b b x" by (simp add: flat_ord_def)
lemma lfp_gfp_compare:
-- "Least and greatest fixed point are either equal, or bot and top"
assumes MLE: "flatf_mono_le B" and MGE: "flatf_mono_ge B"
shows "flatf_lfp B x = flatf_gfp B x
∨ (flatf_lfp B x = bot ∧ flatf_gfp B x = top)"
using fp_compare[OF MLE MGE] .
definition trimono :: "(('a => 'b) => 'a => ('b::{bot,order,top})) => bool"
where "trimono B ≡ (*flatf_mono_le B ∧*) flatf_mono_ge B ∧ mono B"
lemma trimonoI[refine_mono]:
"[|flatf_mono_ge B; mono B|] ==> trimono B"
unfolding trimono_def by auto
lemma trimono_trigger: "trimono B ==> trimono B" .
declaration {* Refine_Mono_Prover.declare_mono_triggers @{thms trimono_trigger} *}
lemma trimonoD_flatf_ge: "trimono B ==> flatf_mono_ge B"
unfolding trimono_def by auto
lemma trimonoD_mono: "trimono B ==> mono B"
unfolding trimono_def by auto
lemmas trimonoD = trimonoD_flatf_ge trimonoD_mono
definition "triords ≡ {flat_ge,op ≤}"
lemma trimono_alt:
"trimono B <-> (∀ord∈fun_ord`triords. monotone ord ord B)"
unfolding trimono_def
by (auto simp: ccpo_mono_simp[symmetric] triords_def
fun_ord_def[abs_def] le_fun_def[abs_def])
lemma trimonoI':
assumes "!!ord. ord∈triords ==> monotone (fun_ord ord) (fun_ord ord) B"
shows "trimono B"
unfolding trimono_alt using assms by blast
definition REC where "REC B x ≡
if (trimono B) then (lfp B x) else (top::'a::complete_lattice)"
definition RECT ("REC⇩T") where "RECT B x ≡
if (trimono B) then (flatf_gfp B x) else (top::'a::complete_lattice)"
lemma RECT_gfp_def: "RECT B x =
(if (trimono B) then (gfp B x) else (top::'a::complete_lattice))"
unfolding RECT_def
by (auto simp: gfp_eq_flatf_gfp[OF trimonoD_flatf_ge trimonoD_mono])
lemma REC_unfold: "trimono B ==> REC B x = B (REC B) x"
unfolding REC_def [abs_def]
by (simp add: lfp_unfold[OF trimonoD_mono, symmetric])
lemma RECT_unfold: "[|trimono B|] ==> RECT B x = B (RECT B) x"
unfolding RECT_def [abs_def]
by (simp add: flatf_ord.fixp_unfold[OF trimonoD_flatf_ge, symmetric])
lemma REC_mono[refine_mono]:
assumes [simp]: "trimono B"
assumes LE: "!!F x. (B F x) ≤ (B' F x)"
shows "(REC B x) ≤ (REC B' x)"
unfolding REC_def
apply clarsimp
apply (rule lfp_mono[THEN le_funD])
apply (rule LE[THEN le_funI])
done
lemma RECT_mono[refine_mono]:
assumes [simp]: "trimono B'"
assumes LE: "!!F x. flat_ge (B F x) (B' F x)"
shows "flat_ge (RECT B x) (RECT B' x)"
unfolding RECT_def
apply clarsimp
apply (rule flatf_fp_mono, (simp_all add: trimonoD) [2])
apply (rule LE)
done
lemma REC_le_RECT: "trimono body ==> REC body x ≤ RECT body x"
unfolding REC_def RECT_gfp_def
apply clarsimp
apply (rule lfp_le_gfp[THEN le_funD])
by (simp add: trimonoD)
print_statement flatf_fp_induct_pointwise
theorem lfp_induct_pointwise:
fixes a::'a
assumes ADM1: "!!a x. chain_admissible (λb. ∀a x. pre a x --> post a x (b x))"
assumes ADM2: "!!a x. pre a x --> post a x bot"
assumes MONO: "mono B"
assumes P0: "pre a x"
assumes IS:
"!!f a x.
[|!!a' x'. pre a' x' ==> post a' x' (f x'); pre a x;
f ≤ (lfp B)|]
==> post a x (B f x)"
shows "post a x (lfp B x)"
proof -
def u≡"lfp B"
have [simp]: "!!f. f≤lfp B ==> B f ≤ lfp B"
by (metis (poly_guards_query) MONO lfp_unfold monoD)
have "(∀a x. pre a x --> post a x (lfp B x)) ∧ lfp B ≤ u"
apply (rule lfp_cadm_induct[where f=B])
apply (rule admissible_conj)
apply (rule ADM1)
apply (rule)
apply (blast intro: Sup_least)
apply (simp add: le_fun_def ADM2) []
apply fact
apply (intro conjI allI impI)
unfolding u_def
apply (blast intro: IS)
apply simp
done
with P0 show ?thesis by blast
qed
lemma REC_rule_arb:
fixes x::"'x" and arb::'arb
assumes M: "trimono body"
assumes I0: "pre arb x"
assumes IS: "!!f arb x. [|
!!arb' x. pre arb' x ==> f x ≤ M arb' x; pre arb x; f ≤ REC body
|] ==> body f x ≤ M arb x"
shows "REC body x ≤ M arb x"
unfolding REC_def
apply (clarsimp simp: M)
apply (rule lfp_induct_pointwise[where pre=pre])
apply (auto intro!: chain_admissibleI SUP_least) [2]
apply (simp add: trimonoD[OF M])
apply (rule I0)
apply (rule IS, assumption+)
apply (auto simp: REC_def[abs_def] intro!: le_funI dest: le_funD) []
done
lemma RECT_rule_arb:
assumes M: "trimono body"
assumes WF: "wf (V::('x×'x) set)"
assumes I0: "pre (arb::'arb) (x::'x)"
assumes IS: "!!f arb x. [|
!!arb' x'. [|pre arb' x'; (x',x)∈V|] ==> f x' ≤ M arb' x';
pre arb x;
RECT body = f
|] ==> body f x ≤ M arb x"
shows "RECT body x ≤ M arb x"
apply (rule wf_fixp_induct[where fp=RECT and pre=pre and B=body])
apply (rule ext)
apply (rule RECT_unfold)
apply (simp_all add: M) [2]
apply (rule WF)
apply fact
apply (rule IS)
apply assumption
apply assumption
apply assumption
done
lemma REC_rule:
fixes x::"'x"
assumes M: "trimono body"
assumes I0: "pre x"
assumes IS: "!!f x. [| !!x. pre x ==> f x ≤ M x; pre x |]
==> body f x ≤ M x"
shows "REC body x ≤ M x"
by (rule REC_rule_arb[where pre="λ_. pre" and M="λ_. M", OF assms])
lemma RECT_rule:
assumes M: "trimono body"
assumes WF: "wf (V::('x×'x) set)"
assumes I0: "pre (x::'x)"
assumes IS: "!!f x. [| !!x'. [|pre x'; (x',x)∈V|] ==> f x' ≤ M x'; pre x;
RECT body = f
|] ==> body f x ≤ M x"
shows "RECT body x ≤ M x"
by (rule RECT_rule_arb[where pre="λ_. pre" and M="λ_. M", OF assms])
lemma REC_rule_arb2:
assumes M: "trimono body"
assumes I0: "pre (arb::'arb) (arc::'arc) (x::'x)"
assumes IS: "!!f arb arc x. [|
!!arb' arc' x'. [|pre arb' arc' x' |] ==> f x' ≤ M arb' arc' x';
pre arb arc x
|] ==> body f x ≤ M arb arc x"
shows "REC body x ≤ M arb arc x"
apply (rule order_trans)
apply (rule REC_rule_arb[
where pre="split pre" and M="split M" and arb="(arb, arc)",
OF M])
by (auto intro: assms)
lemma REC_rule_arb3:
assumes M: "trimono body"
assumes I0: "pre (arb::'arb) (arc::'arc) (ard::'ard) (x::'x)"
assumes IS: "!!f arb arc ard x. [|
!!arb' arc' ard' x'. [|pre arb' arc' ard' x'|] ==> f x' ≤ M arb' arc' ard' x';
pre arb arc ard x
|] ==> body f x ≤ M arb arc ard x"
shows "REC body x ≤ M arb arc ard x"
apply (rule order_trans)
apply (rule REC_rule_arb2[
where pre="split pre" and M="split M" and arb="(arb, arc)" and arc="ard",
OF M])
by (auto intro: assms)
lemma RECT_rule_arb2:
assumes M: "trimono body"
assumes WF: "wf (V::'x rel)"
assumes I0: "pre (arb::'arb) (arc::'arc) (x::'x)"
assumes IS: "!!f arb arc x. [|
!!arb' arc' x'. [|pre arb' arc' x'; (x',x)∈V|] ==> f x' ≤ M arb' arc' x';
pre arb arc x;
f ≤ RECT body
|] ==> body f x ≤ M arb arc x"
shows "RECT body x ≤ M arb arc x"
apply (rule order_trans)
apply (rule RECT_rule_arb[
where pre="split pre" and M="split M" and arb="(arb, arc)",
OF M WF])
by (auto intro: assms)
lemma RECT_rule_arb3:
assumes M: "trimono body"
assumes WF: "wf (V::'x rel)"
assumes I0: "pre (arb::'arb) (arc::'arc) (ard::'ard) (x::'x)"
assumes IS: "!!f arb arc ard x. [|
!!arb' arc' ard' x'. [|pre arb' arc' ard' x'; (x',x)∈V|] ==> f x' ≤ M arb' arc' ard' x';
pre arb arc ard x;
f ≤ RECT body
|] ==> body f x ≤ M arb arc ard x"
shows "RECT body x ≤ M arb arc ard x"
apply (rule order_trans)
apply (rule RECT_rule_arb2[
where pre="split pre" and M="split M" and arb="(arb, arc)" and arc="ard",
OF M WF])
by (auto intro: assms)
lemma RECT_eq_REC:
-- "Partial and total correct recursion are equal if total
recursion does not fail."
assumes M: "trimono body"
assumes NT: "RECT body x ≠ top"
shows "RECT body x = REC body x"
using NT M
unfolding RECT_def REC_def
proof clarsimp
from lfp_unfold[OF trimonoD_mono[OF M], symmetric]
have "flatf_ge (body (lfp body)) (lfp body)" by simp
note flatf_ord.fixp_lowerbound[
OF trimonoD_flatf_ge[OF M], of "lfp body", OF this]
moreover assume "flatf_gfp body x ≠ top"
ultimately show "flatf_gfp body x = lfp body x"
by (auto simp add: fun_ord_def flat_ord_def)
qed
lemma RECT_eq_REC_tproof:
-- "Partial and total correct recursion are equal if we can provide a
termination proof."
fixes a :: 'a
assumes M: "trimono body"
assumes WF: "wf V"
assumes I0: "pre a x"
assumes IS: "!!f arb x.
[|!!arb' x'. [|pre arb' x'; (x', x) ∈ V|] ==> f x' ≤ M arb' x';
pre arb x; REC⇩T body = f|]
==> body f x ≤ M arb x"
assumes NT: "M a x ≠ top"
shows "RECT body x = REC body x ∧ RECT body x ≤ M a x"
proof
show "RECT body x ≤ M a x"
by (rule RECT_rule_arb[OF M WF, where pre=pre, OF I0 IS])
with NT have "RECT body x ≠ top" by (metis top.extremum_unique)
thus "RECT body x = REC body x" by (rule RECT_eq_REC[OF M])
qed
subsection {* Transfer *}
lemma (in transfer) transfer_RECT'[refine_transfer]:
assumes REC_EQ: "!!x. fr x = b fr x"
assumes REF: "!!F f x. [|!!x. α (f x) ≤ F x |] ==> α (b f x) ≤ B F x"
shows "α (fr x) ≤ RECT B x"
unfolding RECT_def
proof clarsimp
assume MONO: "trimono B"
show "α (fr x) ≤ flatf_gfp B x"
apply (rule flatf_fixp_transfer[where B=B and fp'=fr and P="op =",
OF _ trimonoD_flatf_ge[OF MONO]])
apply simp
apply (rule ext, fact)
apply (simp)
apply (simp,rule REF, blast)
done
qed
lemma (in ordered_transfer) transfer_RECT[refine_transfer]:
assumes REF: "!!F f x. [|!!x. α (f x) ≤ F x |] ==> α (b f x) ≤ B F x"
assumes M: "trimono b"
shows "α (RECT b x) ≤ RECT B x"
apply (rule transfer_RECT')
apply (rule RECT_unfold[OF M])
by fact
lemma (in dist_transfer) transfer_REC[refine_transfer]:
assumes REF: "!!F f x. [|!!x. α (f x) ≤ F x |] ==> α (b f x) ≤ B F x"
assumes M: "trimono b"
shows "α (REC b x) ≤ REC B x"
unfolding REC_def
apply (clarsimp simp: M)
apply (rule lfp_induct_pointwise[where B=b and pre="op="])
apply (rule)
apply clarsimp
apply (subst SUP_def)
apply (subst α_dist)
apply (auto simp add: chain_def le_fun_def) []
apply (rule Sup_least)
apply auto []
apply simp
apply (simp add: trimonoD[OF M])
apply (rule refl)
apply (subst lfp_unfold)
apply (simp add: trimonoD)
apply (rule REF)
apply blast
done
end