Theory FixedPointTheorems

(*<*)
(*
 * The worker/wrapper transformation, following Gill and Hutton.
 * (C)opyright 2009-2011, Peter Gammie, peteg42 at gmail.com.
 * License: BSD
 *)

theory FixedPointTheorems
imports
  HOLCF
begin

setup Document_Output.antiquotation_raw bindinghaskell (Scan.lift Args.name)
    (fn _ => fn s => Latex.string ("\\" ^ "<" ^ s ^ "\\>"))

(* LaTeXsugar fights with HOLCF syntax: at least cdot *)

(* THEOREMS *)
notation (Rule output)
  Pure.imp  ("latex‹\\mbox{}\\inferrule{\\mbox{›_latex‹}}›latex‹{\\mbox{›_latex‹}}›")

syntax (Rule output)
  "_bigimpl" :: "asms  prop  prop"
  ("latex‹\\mbox{}\\inferrule{›_latex‹}›latex‹{\\mbox{›_latex‹}}›")

  "_asms" :: "prop  asms  asms"
  ("latex‹\\mbox{›_latex‹}\\\\›/ _")

  "_asm" :: "prop  asms" ("latex‹\\mbox{›_latex‹}›")

(*>*)
section‹Fixed-point theorems for program transformation›

text‹

We begin by recounting some standard theorems from the early days of
denotational semantics. The origins of these results are lost to
history; the interested reader can find some of it in
citet"Bekic:1969" and "Manna:1974" and "Greibach:1975" and "Stoy:1977" and "DBLP:books/daglib/0002432" and "Harel:1980" and "Plotkin:1983" and "Winskel:1993" and "DBLP:journals/toplas/Sangiorgi09".

›

subsection‹The rolling rule›

text‹

The \emph{rolling rule} captures what intuitively happens when we
re-order a recursive computation consisting of two parts. This theorem
dates from the 1970s at the latest -- see citet‹p210› in "Stoy:1977" and
citet"Plotkin:1983". The following proofs were provided by
citet"GillHutton:2009".

›

lemma rolling_rule_ltr: "fix(g oo f)  g(fix(f oo g))"
proof -
  have "g(fix(f oo g))  g(fix(f oo g))"
    by (rule below_refl) ― ‹reflexivity›
  hence "g((f oo g)(fix(f oo g)))  g(fix(f oo g))"
    using fix_eq[where F="f oo g"] by simp ― ‹computation›
  hence "(g oo f)(g(fix(f oo g)))  g(fix(f oo g))"
    by simp ― ‹re-associate @{term "(oo)"}
  thus "fix(g oo f)  g(fix(f oo g))"
    using fix_least_below by blast ― ‹induction›
qed

lemma rolling_rule_rtl: "g(fix(f oo g))  fix(g oo f)"
proof -
  have "fix(f oo g)  f(fix(g oo f))" by (rule rolling_rule_ltr)
  hence "g(fix(f oo g))  g(f(fix(g oo f)))"
    by (rule monofun_cfun_arg) ― ‹g is monotonic›
  thus "g(fix(f oo g))  fix(g oo f)"
    using fix_eq[where F="g oo f"] by simp ― ‹computation›
qed

lemma rolling_rule: "fix(g oo f) = g(fix(f oo g))"
  by (rule below_antisym[OF rolling_rule_ltr rolling_rule_rtl])
(*

This property of a fixed-point operator is termed \emph{dinaturality}
by \citet{DBLP:conf/lics/SimpsonP00}.

*)

subsection‹Least-fixed-point fusion›

text‹

\label{sec:lfp-fusion}

\emph{Least-fixed-point fusion} provides a kind of induction that has
proven to be very useful in calculational settings. Intuitively it
lifts the step-by-step correspondence between @{term "f"} and @{term
"h"} witnessed by the strict function @{term "g"} to the fixed points
of @{term "f"} and @{term "g"}:
\[
  \begin{diagram}
    \node{\bullet} \arrow{e,t}{h} \node{\bullet}\\
    \node{\bullet} \arrow{n,l}{g} \arrow{e,b}{f} \node{\bullet} \arrow{n,r}{g}
  \end{diagram}
  \qquad \Longrightarrow \qquad
  \begin{diagram}
    \node{\mathsf{fix}\ h}\\
    \node{\mathsf{fix}\ f} \arrow{n,r}{g}
  \end{diagram}
\]
\citet*{FokkingaMeijer:1991}, and also their later
\citet*{barbed-wire:1991}, made extensive use of this rule, as did
citet"Tullsen:PhDThesis" in his program transformation tool PATH.
This diagram is strongly reminiscent of the simulations used to
establish refinement relations between imperative programs and their
specifications \citep*{EdR:cup98}.

The following proof is close to the third variant of
citet‹p215› in "Stoy:1977". We relate the two fixpoints using the rule
\texttt{parallel\_fix\_ind}:
\begin{center}
  @{thm[mode=Rule] parallel_fix_ind}
\end{center}
in a very straightforward way:

›

lemma lfp_fusion:
  assumes "g = "
  assumes "g oo f = h oo g"
  shows "g(fixf) = fixh"
proof(induct rule: parallel_fix_ind)
  case 2 show "g = " by fact
  case (3 x y)
  from gx = y g oo f = h oo g show "g(fx) = hy"
    by (simp add: cfun_eq_iff)
qed simp

text‹

This lemma also goes by the name of \emph{Plotkin's axiom}
citep"PittsAM:relpod" or \emph{uniformity}
citep"DBLP:conf/lics/SimpsonP00".

›
(*<*)

(* The rest of this theory is only of historical interest. *)

text ‹Some may find the pointed version easier to read.›

lemma lfp_fusion_pointed:
  assumes Cfg: "f. C(Ff) = G(Cf)"
      and strictC: "C = "
  shows "C(fixF) = fixG"
  using lfp_fusion[where f=F and g=C and h=G] assms
  by (simp add: cfcomp1)

subsubsection‹More about lfp-fusion›

text‹

Alternative proofs. This is the ``intuitive'' one
citet‹p125› in "Gunter:1992" and citet‹p46› in "Tullsen:PhDThesis", where we
can shuffle @{term "g"} to the end of the the iteration of @{term "f"}
using @{term "fgh"}.

›

lemma lfp_fusion2_aux:
  assumes fgh: "g oo f = h oo g"
  shows "g(iterate if) = iterate ih(g)"
proof(induct i)
  case (Suc i)
  have "g(iterate (Suc i)f) = (g oo f)(iterate if)" by simp
  also have "... = h(g(iterate if))" using fgh by (simp add: cfcomp1)
  also have "... = h(iterate ih(g))" using Suc by simp
  also have "... = iterate (Suc i)h(g)" by simp
  finally show ?case .
qed simp

lemma lfp_fusion2:
  assumes fgh: "g oo f = h oo g"
      and strictg: "g = "
  shows "g(fixf) = fixh"
proof -
  have "g(fixf) = g(i. iterate if)" by (simp only: fix_def2)
  also have "... = (i. g(iterate if))" by (simp add: contlub_cfun_arg)
  also have "... = (i. (iterate ih(g)))" by (simp only: lfp_fusion2_aux[OF fgh])
  also have "... = fixh" using strictg by (simp only: fix_def2)
  finally show ?thesis .
qed

text‹This is the first one by citet‹p213› in "Stoy:1977", almost
identical to the above.›

lemma lfp_fusion3_aux:
  assumes fgh: "g oo f = h oo g"
      and strictg: "g = "
  shows "g(iterate if) = iterate ih"
proof(induct i)
  case 0 from strictg show ?case by simp
next
  case (Suc i)
  have "g(iterate (Suc i)f) = (g oo f)(iterate if)" by simp
  also have "... = h(g(iterate if))" using fgh by (simp add: cfcomp1)
  also have "... = h(iterate ih)" using Suc by simp
  also have "... = iterate (Suc i)h" by simp
  finally show ?case .
qed

lemma lfp_fusion3:
  assumes fgh: "g oo f = h oo g"
      and strictg: "g = "
  shows "g(fixf) = fixh"
proof -
  have "g(fixf) = g(i. iterate if)" by (simp only: fix_def2)
  also have "... = (i. g(iterate if))" by (simp add: contlub_cfun_arg)
  also have "... = (i. (iterate ih))" by (simp only: lfp_fusion3_aux[OF fgh strictg])
  also have "... = fixh" by (simp only: fix_def2)
  finally show ?thesis .
qed

text‹Stoy's second proof citep‹p214› in "Stoy:1977" is similar to the
original proof using fixed-point induction.›

lemma lfp_fusion4:
  assumes fgh: "g oo f = h oo g"
      and strictg: "g = "
  shows "g(fixf) = fixh"
proof(rule below_antisym)
  show "fixh  g(fixf)"
  proof -
    have "h(g(fixf)) = (g oo f)(fixf)" using fgh by simp
    also have "... = g(fixf)" by (subst fix_eq, simp)
    finally show ?thesis by (rule fix_least)
  qed
  let ?P = "λx. gx  fixh"
  show "?P (fixf)"
  proof(induct rule: fix_ind[where P="?P"])
    case 2 with strictg show ?case by simp
  next
    case (3 x) hence indhyp: "gx  fixh" .
    have "g(fx) = (h oo g)x" using fgh[symmetric] by simp
    with indhyp show "g(fx)  fixh"
      by (subst fix_eq, simp add: monofun_cfun)
  qed simp
qed

text‹A wrinkly variant from citet‹p11› in "barbed-wire:1991".›

lemma lfp_fusion_barbed_variant:
  assumes ff': "f = f'"
      and fgh: "f oo g = h oo f"
      and f'g'h: "f' oo g' = h oo f'"
  shows "f(fixg) = f'(fixg')"
proof(induct rule: parallel_fix_ind)
  case 2 show "f = f'" by (rule ff')
  case (3 x y)
  from fx = f'y have "h(fx) = h(f'y)" by simp
  with fgh f'g'h have "f(gx) = f'(g'y)"
    using cfcomp2[where f="f" and g="g", symmetric]
          cfcomp2[where f="f'" and g="g'", symmetric]
    by simp
  thus ?case by simp
qed simp
(*>*)

(*<*)
end
(*>*)