Theory Psi

subsection ‹Definition of \texorpdfstring{$\Psi$}{Psi}\label{sec:psi}›

theory Psi
  imports SortKeys "HOL-Eisbach.Eisbach"
begin

fun extended_size :: "('ℐ sort_key) extended  nat"
  where
    "extended_size x = size x" |
    "extended_size _ = 0"

lemma extended_simps [simp]:
  "( < x) = (x  )"
  "(x' < y') = (x' < y')"
  "x' < "
  "¬(x' < )"
  "¬( < x)"
  "  x"
  "(x'  y') = ((x' :: 'ℐ :: linorder)  y')"
  "x  "
  "¬(x'  )"
  "(  x) = (x = )"
  by (case_tac [!] x, simp_all add:less_extended_def less_eq_extended_def le_less)

fun int_size where "int_size (l,u) = max (extended_size l) (extended_size u)"

lemma position_cases:
  assumes " y z. x = NonFinal (y,Left) z  p"
  assumes " y z. x = NonFinal (y,Right) z  p"
  assumes " y. x = Final y  p"
  assumes "x =   p"
  assumes "x =   p"
  shows "p"
  by (metis assms embed_dir.cases extended_size.cases sort_key_embedding.cases)

fun derive_pos ::
  "('ℐ :: linorder) × sort_dir  'ℐ sort_key extended  'ℐ sort_key extended"
  where
    "derive_pos h NonFinal x y = 
      (if h < x then  else (if x < h then  else y))" |
    "derive_pos h Final x = 
      (if fst h < x  fst h = x  snd h = Left then  else )" |
    "derive_pos _  = " |
    "derive_pos _  = "

lemma derive_pos_mono: "x  y  derive_pos h x  derive_pos h y"
  apply (cases h, cases "snd h")
  apply (rule_tac [!] position_cases [where x=x])
  apply (rule_tac [!] position_cases [where x=y])
  by (simp_all, auto)

fun γ :: "('ℐ :: linorder) position  sort_dir  'ℐ × sort_dir"
  where
    "γ NonFinal x y _ = x" |
    "γ Final x d = (x,d)" |
    "γ  _ = undefined" |
    "γ  _ = undefined"

fun derive_left  where
  "derive_left (l, u) = (derive_pos (γ l Right) l, derive_pos (γ l Right) u)"

fun derive_right where
  "derive_right (l, u) = (derive_pos (γ u Left) l, derive_pos (γ u Left) u)"

fun is_interval where "is_interval (l,u) = (l < u)"

fun elem where "elem x (l,u) = (l < x  x < u)"

fun subset where "subset (l,u) (l',u') = (l'  l  u  u')"

method interval_split for x :: "('ℐ :: linorder) position × 'ℐ position" = 
  (case_tac [!] x, 
   rule_tac [!] position_cases [where x="fst x"], 
   rule_tac [!] position_cases [where x="snd x"])

lemma derive_size:
  "Final i  fst x  is_interval x  int_size (derive_left x) < int_size x" 
  "snd x  Final i  is_interval x  int_size (derive_right x) < int_size x"
  by (interval_split x, simp_all add:less_SucI)

lemma derive_interval:
  "Final i  fst x  is_interval x  is_interval (derive_left x)"
  "snd x  Final i  is_interval x  is_interval (derive_right x)"
  by (interval_split x, simp_all, auto)

function Ψ :: "('ℐ :: linorder) position × 'ℐ position  'ℐ  'ℐ sort_key"
  where
    "Ψ (l,u) i = Final i"
      if "l < Final i  Final i < u" |
    "Ψ (l,u) i = NonFinal (γ l Right) (Ψ (derive_left (l,u)) i)" 
      if "Final i  l  l < u" |
    "Ψ (l,u) i = NonFinal (γ u Left) (Ψ (derive_right (l,u)) i)" 
      if "u  Final i  l < u" |
    "Ψ (l,u) i = undefined" if "u  l"
  by (metis leI old.prod.exhaust, auto)

termination
  apply (relation "measure (λ(p,i). int_size p)", simp)
  using derive_size by fastforce+

proposition psi_elem: "is_interval x  elem Ψ x i x"
proof (induct "int_size x" arbitrary:x rule: nat_less_induct)
  case 1
  consider (a) "Final i  fst x" | (b) "elem Final i x" | (c) "snd x  Final i"
    using not_le by (metis elem.simps prod.collapse)
  then show ?case
  proof (cases)
    case a
    hence "elem  Ψ (derive_left x) i (derive_left x)"
      by (metis 1 derive_size(1) derive_interval(1))
    then show ?thesis using a "1"(2)
      by (interval_split x, simp_all del:Ψ.simps, auto)
  next
    case b
    then show ?thesis by (cases x, simp)
  next
    case c 
    hence "elem  Ψ (derive_right x) i (derive_right x)"
      by (metis 1 derive_size(2) derive_interval(2))
    then show ?thesis using c "1"(2)
      by (interval_split x, simp_all del:Ψ.simps, auto)
  qed
qed

proposition psi_mono:
  assumes "i1 < i2"
  shows "is_interval x  Ψ x i1 < Ψ x i2"
proof (induct "int_size x" arbitrary:x rule: nat_less_induct)
  case 1
  have a:"Final i1 < Final i2"
    using assms by auto
  then consider 
    (a) "Final i1  fst x  Final i2  fst x" | 
    (b) "Final i1  fst x  elem Final i2 x" | 
    (c) "Final i1  fst x  snd x  Final i2" |
    (d) "elem Final i1 x   elem Final i2 x" |
    (e) "elem Final i1 x  snd x  Final i2" |
    (f) "snd x  Final i2  snd x  Final i1" 
    using assms "1"(2) apply (cases x) 
    by (metis (mono_tags, opaque_lifting) dual_order.strict_trans elem.simps
        fst_conv leI snd_conv)
  then show ?case
  proof (cases)
    case a
    hence "Ψ (derive_left x) i1  < Ψ (derive_left x) i2"
      by (metis 1 derive_size(1) derive_interval(1))
    thus ?thesis using a "1"(2) by (cases x, simp)
  next
    case b
    thus ?thesis using "1"(2) apply (cases x, simp) 
      by (rule_tac [!] position_cases [where x="fst x"], simp_all)
  next
    case c
    show ?thesis
    proof (cases "γ (fst x) Right = γ (snd x) Left")
      case True 
      have e:"is_interval (derive_left x)" using c "1"(2) derive_interval(1) by blast
      have f:"derive_left x = derive_right x" using True by (cases x, simp)
      have h:"Ψ (derive_left x) i1 < Ψ (derive_right x) i2"
        apply (cases x, simp only: f) 
        by (metis "1.hyps" "1.prems" c derive_size(2) e f)
      show ?thesis using c "1"(2) h True by (cases x, simp)
    next
      case False
      hence "γ (fst x) Right < γ (snd x) Left" using "1"(2) c
      by (interval_split x, simp_all, auto)
      then show ?thesis using c "1"(2) by (cases x, simp)
    qed
  next
    case d
    thus ?thesis using "1"(2) a by (cases x, simp)
  next
    case e
    thus ?thesis using "1"(2) apply (cases x, simp) 
      by (rule_tac [!] position_cases [where x="snd x"], simp_all del:Ψ.simps)
  next
    case f
    hence b:"Ψ (derive_right x) i1  < Ψ (derive_right x) i2" 
      by (metis 1 derive_size(2) derive_interval(2))
    thus ?thesis using f "1"(2) by (cases x, simp)
  qed
qed

proposition psi_narrow:
  "elem Ψ x' i x  subset x x'  Ψ x' i = Ψ x i" 
proof (induct "int_size x'" arbitrary: x x' rule: nat_less_induct)
  case 1
  have a: "is_interval x" using "1"(2)
    by (metis dual_order.strict_trans elem.elims(2) is_interval.simps)
  have d: "is_interval x'" using a "1"(3) apply (cases x', cases x, simp) by auto
  consider
    (before) "Final i  fst x'" |
    (between) "elem Final i x'" | 
    (after) "snd x'  Final i" using 1 apply simp
    by (metis elem.simps leI prod.collapse)
  then show ?case
  proof (cases)
    case before
    have b: "Final i  fst x" using before 1 apply (cases x)
      by (metis dual_order.trans fst_conv subset.elims(2))
    obtain z where z_def: "Ψ x' i = NonFinal (γ (fst x') Right) z" 
      using before d apply (cases x') by simp
    have c:"γ (fst x') Right = γ (fst x) Right"
      using "1"(3) z_def "1"(2) apply (cases x, cases x', simp)
      apply (rule_tac [!] position_cases [where x="fst x"])
      apply (rule_tac [!] position_cases [where x="fst x'"])
      using before by (simp_all del:Ψ.simps, auto)
    have c1:"subset (derive_left x) (derive_left x')"
      using c "1"(3) by (cases x, cases x', simp add:derive_pos_mono)
    have g:"z = Ψ (derive_left x') i" using z_def before d by (cases x', simp)
    have "elem NonFinal (γ (fst x) Right) z x" 
      using "1"(2) z_def by (simp add: c)
    hence "elem z (derive_left x)" using before b
      by (interval_split x, simp_all del:Ψ.simps, auto)
    hence "Ψ (derive_left x') i = Ψ (derive_left x) i"
      using "1"(1) before d c1 apply (simp only:g)
      by (metis (no_types) derive_size(1))
    thus ?thesis using before b a d c by (cases x, cases x', simp)
  next
    case between
    thus ?thesis using 1 by (cases x, cases x', auto) 
  next
    case after
    have b: "snd x  Final i" using after 1 apply (cases x) 
      by (metis (mono_tags, opaque_lifting) dual_order.trans prod.exhaust_sel
          subset.simps)
    obtain z where z_def:"Ψ x' i = NonFinal (γ (snd x') Left) z" 
      using after d by (cases x', simp)
    have c:"γ (snd x') Left = γ (snd x) Left"
      using "1"(3) z_def "1"(2) apply (simp, cases x, cases x')
      apply (rule_tac [!] position_cases [where x="snd x"])
      apply (rule_tac [!] position_cases [where x="snd x'"]) using after
      by (simp_all del:Ψ.simps, auto)
    have c1:"subset (derive_right x) (derive_right x')"
      using c "1"(3) by (cases x, cases x', simp add:derive_pos_mono)
    have g:"z = Ψ (derive_right x') i" using z_def after d by (cases x', simp)
    have "elem NonFinal (γ (snd x) Left) z x" 
      using "1"(2) z_def by (simp add: c)
    hence "elem z (derive_right x)" using after b
      by (interval_split x, simp_all del:Ψ.simps, auto)
    hence "Ψ (derive_right x') i = Ψ (derive_right x) i"
      using "1"(1) after d c1 apply (simp only:g)   
      by (metis (no_types) derive_size(2))
    thus ?thesis using after b a d c by (cases x, cases x', simp)
  qed
qed

definition preserve_order :: "'a :: linorder  'a  'b :: linorder  'b  bool"
  where "preserve_order x y u v  (x < y  u < v)  (x > y  u > v)"

proposition psi_preserve_order:
  fixes l l' u u' i i'
  assumes "elem Ψ (l, u) i (l',u')"
  assumes "elem Ψ (l', u') i' (l, u)"
  shows "preserve_order i i' Ψ (l,u) i Ψ (l', u') i'"
proof -
  have "l < u" using assms(2) by auto
  hence a:"elem Ψ (l, u) i (max l l', min u u')"
    using assms(1) psi_elem by fastforce
  hence b:"Ψ (l,u) i = Ψ (max l l', min u u') i"
    by (simp add: psi_narrow)
  have "l' < u'" using assms(1) by auto
  hence "elem Ψ (l',u') i' (max l l', min u u')"
    using assms(2) psi_elem by fastforce
  hence c:"Ψ (l',u') i' = Ψ (max l l', min u u') i'"
    by (simp add: psi_narrow)
  hence "max l l' < min u u'" using a min_def by auto
  then show ?thesis apply (simp only: preserve_order_def b c)
    using psi_mono extended_simps(2) is_interval.simps by blast
qed

end