Theory StutteringLemmas

subsection‹Stuttering Lemmas›

theory StutteringLemmas

imports StutteringDefs

begin

text ‹
  In this section, we prove several lemmas that will be used to show that TESL 
  specifications are invariant by stuttering.

  The following one will be useful in proving properties over a sequence of 
  stuttering instants.
›
lemma bounded_suc_ind:
  assumes k. k < m  P (Suc (z + k)) = P (z + k)
    shows k < m  P (Suc (z + k)) = P z
proof (induction k)
  case 0
    with assms(1)[of 0] show ?case by simp
next
  case (Suc k')
    with assms[of Suc k'] show ?case by force
qed

subsection ‹Lemmas used to prove the invariance by stuttering›

text ‹Since a dilating function is strictly monotonous, it is injective.›

lemma dilating_fun_injects:
  assumes dilating_fun f r
  shows   inj_on f A
using assms dilating_fun_def strict_mono_imp_inj_on by blast

lemma dilating_injects:
  assumes dilating f sub r
  shows   inj_on f A
using assms dilating_def dilating_fun_injects by blast

text ‹
  If a clock ticks at an instant in a dilated run, that instant is the image
  by the dilating function of an instant of the original run.
›
lemma ticks_image:
  assumes dilating_fun f r
  and     hamlet ((Rep_run r) n c)
  shows   n0. f n0 = n
using dilating_fun_def assms by blast

lemma ticks_image_sub:
  assumes dilating f sub r
  and     hamlet ((Rep_run r) n c)
  shows   n0. f n0 = n
using assms dilating_def ticks_image by blast

lemma ticks_image_sub':
  assumes dilating f sub r
  and     c. hamlet ((Rep_run r) n c)
  shows   n0. f n0 = n
using ticks_image_sub[OF assms(1)] assms(2) by blast


text ‹ 
  The image of the ticks in an interval by a dilating function is the interval 
  bounded by the image of the bounds of the original interval.
  This is proven for all 4 kinds of intervals:  ‹]m, n[›, ‹[m, n[›, ‹]m, n]›
  and ‹[m, n]›.
›

lemma dilating_fun_image_strict:
  assumes dilating_fun f r
  shows   {k. f m < k  k < f n  hamlet ((Rep_run r) k c)}
            = image f {k. m < k  k < n  hamlet ((Rep_run r) (f k) c)}
  (is ?IMG = image f ?SET)
proof
  { fix k assume h:k  ?IMG
    from h obtain k0 where k0prop:f k0 = k  hamlet ((Rep_run r) (f k0) c)
      using ticks_image[OF assms] by blast
    with h have k  image f ?SET
      using assms dilating_fun_def strict_mono_less by blast
  } thus ?IMG  image f ?SET ..
next
  { fix k assume h:k  image f ?SET
    from h obtain k0 where k0prop:k = f k0  k0  ?SET by blast
    hence k  ?IMG using assms by (simp add: dilating_fun_def strict_mono_less)
  } thus image f ?SET  ?IMG ..
qed

lemma dilating_fun_image_left:
  assumes dilating_fun f r
  shows   {k. f m  k  k < f n  hamlet ((Rep_run r) k c)}
          = image f {k. m  k  k < n  hamlet ((Rep_run r) (f k) c)}
  (is ?IMG = image f ?SET)
proof
  { fix k assume h:k  ?IMG
    from h obtain k0 where k0prop:f k0 = k  hamlet ((Rep_run r) (f k0) c)
      using ticks_image[OF assms] by blast
    with h have k  image f ?SET
      using assms dilating_fun_def strict_mono_less strict_mono_less_eq by fastforce
  } thus ?IMG  image f ?SET ..
next
  { fix k assume h:k  image f ?SET
    from h obtain k0 where k0prop:k = f k0  k0  ?SET by blast
    hence k  ?IMG
      using assms dilating_fun_def strict_mono_less strict_mono_less_eq by fastforce
  } thus image f ?SET  ?IMG ..
qed

lemma dilating_fun_image_right:
  assumes dilating_fun f r
  shows   {k. f m < k  k  f n  hamlet ((Rep_run r) k c)}
          = image f {k. m < k  k  n  hamlet ((Rep_run r) (f k) c)}
  (is ?IMG = image f ?SET)
proof
  { fix k assume h:k  ?IMG
    from h obtain k0 where k0prop:f k0 = k  hamlet ((Rep_run r) (f k0) c)
      using ticks_image[OF assms] by blast
    with h have k  image f ?SET
      using assms dilating_fun_def strict_mono_less strict_mono_less_eq by fastforce
  } thus ?IMG  image f ?SET ..
next
  { fix k assume h:k  image f ?SET
    from h obtain k0 where k0prop:k = f k0  k0  ?SET by blast
    hence k  ?IMG
      using assms dilating_fun_def strict_mono_less strict_mono_less_eq by fastforce
  } thus image f ?SET  ?IMG ..
qed

lemma dilating_fun_image:
  assumes dilating_fun f r
  shows   {k. f m  k  k  f n  hamlet ((Rep_run r) k c)}
          = image f {k. m  k  k  n  hamlet ((Rep_run r) (f k) c)}
  (is ?IMG = image f ?SET)
proof
  { fix k assume h:k  ?IMG
    from h obtain k0 where k0prop:f k0 = k  hamlet ((Rep_run r) (f k0) c)
      using ticks_image[OF assms] by blast
    with h have k  image f ?SET
      using assms dilating_fun_def strict_mono_less_eq by blast
  } thus ?IMG  image f ?SET ..
next
  { fix k assume h:k  image f ?SET
    from h obtain k0 where k0prop:k = f k0  k0  ?SET by blast
    hence k  ?IMG using assms by (simp add: dilating_fun_def strict_mono_less_eq)
  } thus image f ?SET  ?IMG ..
qed

text ‹
  On any clock, the number of ticks in an interval is preserved
  by a dilating function.
›
lemma ticks_as_often_strict:
  assumes dilating_fun f r
  shows   card {p. n < p  p < m  hamlet ((Rep_run r) (f p) c)}
          = card {p. f n < p  p < f m  hamlet ((Rep_run r) p c)}
    (is card ?SET = card ?IMG)
proof -
  from dilating_fun_injects[OF assms] have inj_on f ?SET .
  moreover have finite ?SET by simp
  from inj_on_iff_eq_card[OF this] calculation
    have card (image f ?SET) = card ?SET by blast
  moreover from dilating_fun_image_strict[OF assms] have ?IMG = image f ?SET .
  ultimately show ?thesis by auto
qed

lemma ticks_as_often_left:
  assumes dilating_fun f r
  shows   card {p. n  p  p < m  hamlet ((Rep_run r) (f p) c)}
          = card {p. f n  p  p < f m  hamlet ((Rep_run r) p c)}
    (is card ?SET = card ?IMG)
proof -
  from dilating_fun_injects[OF assms] have inj_on f ?SET .
  moreover have finite ?SET by simp
  from inj_on_iff_eq_card[OF this] calculation
    have card (image f ?SET) = card ?SET by blast
  moreover from dilating_fun_image_left[OF assms] have ?IMG = image f ?SET .
  ultimately show ?thesis by auto
qed

lemma ticks_as_often_right:
  assumes dilating_fun f r
  shows   card {p. n < p  p  m  hamlet ((Rep_run r) (f p) c)}
          = card {p. f n < p  p  f m  hamlet ((Rep_run r) p c)}
    (is card ?SET = card ?IMG)
proof -
  from dilating_fun_injects[OF assms] have inj_on f ?SET .
  moreover have finite ?SET by simp
  from inj_on_iff_eq_card[OF this] calculation
    have card (image f ?SET) = card ?SET by blast
  moreover from dilating_fun_image_right[OF assms] have ?IMG = image f ?SET .
  ultimately show ?thesis by auto
qed

lemma ticks_as_often:
  assumes dilating_fun f r
  shows   card {p. n  p  p  m  hamlet ((Rep_run r) (f p) c)}
          = card {p. f n  p  p  f m  hamlet ((Rep_run r) p c)}
    (is card ?SET = card ?IMG)
proof -
  from dilating_fun_injects[OF assms] have inj_on f ?SET .
  moreover have finite ?SET by simp
  from inj_on_iff_eq_card[OF this] calculation
    have card (image f ?SET) = card ?SET by blast
  moreover from dilating_fun_image[OF assms] have ?IMG = image f ?SET .
  ultimately show ?thesis by auto
qed

text ‹The date of an event is preserved by dilation.›

lemma ticks_tag_image:
  assumes dilating f sub r
  and     c. hamlet ((Rep_run r) k c)
  and     time ((Rep_run r) k c) = τ
  shows   k0. f k0 = k  time ((Rep_run sub) k0 c) = τ
proof -
  from ticks_image_sub'[OF assms(1,2)] have k0. f k0 = k .
  from this obtain k0 where f k0 = k by blast
  moreover with assms(1,3) have time ((Rep_run sub) k0 c) = τ
    by (simp add: dilating_def) 
  ultimately show ?thesis by blast
qed

text ‹TESL operators are invariant by dilation.›

lemma ticks_sub:
  assumes dilating f sub r
  shows   hamlet ((Rep_run sub) n a) = hamlet ((Rep_run r) (f n) a)
using assms by (simp add: dilating_def)

lemma no_tick_sub:
  assumes dilating f sub r
  shows   (n0. f n0 = n)  ¬hamlet ((Rep_run r) n a)
using assms dilating_def dilating_fun_def by blast

text ‹Lifting a total function to a partial function on an option domain.›

definition opt_lift::('a  'a)  ('a option  'a option)
where
  opt_lift f  λx. case x of None  None | Some y  Some (f y)

text ‹
  The set of instants when a clock ticks in a dilated run is the image by the 
  dilation function of the set of instants when it ticks in the subrun.
›
lemma tick_set_sub:
  assumes dilating f sub r
  shows   {k. hamlet ((Rep_run r) k c)} = image f {k. hamlet ((Rep_run sub) k c)}
    (is ?R = image f ?S)
proof
  { fix k assume h:k  ?R
    with no_tick_sub[OF assms] have k0. f k0 = k by blast
    from this obtain k0 where k0prop:f k0 = k by blast
    with ticks_sub[OF assms] h have hamlet ((Rep_run sub) k0 c) by blast
    with k0prop have k  image f ?S by blast
  }
  thus ?R  image f ?S by blast
next
  { fix k assume h:k  image f ?S
    from this obtain k0 where f k0 = k  hamlet ((Rep_run sub) k0 c) by blast
    with assms have k  ?R using ticks_sub by blast 
  }
  thus image f ?S  ?R by blast
qed

text ‹
  Strictly monotonous functions preserve the least element.
›
lemma Least_strict_mono:
  assumes strict_mono f
  and     x  S. y  S. x  y
  shows   (LEAST y. y  f ` S) = f (LEAST x. x  S)
using Least_mono[OF strict_mono_mono, OF assms] .

text ‹
  A non empty set of @{typ nat}s has a least element.
›
lemma Least_nat_ex:
  (n::nat)  S  x  S. (y  S. x  y)
by (induction n rule: nat_less_induct, insert not_le_imp_less, blast)

text ‹  
  The first instant when a clock ticks in a dilated run is the image by the dilation
  function of the first instant when it ticks in the subrun.
›
lemma Least_sub:
  assumes dilating f sub r
  and     k::nat. hamlet ((Rep_run sub) k c)
  shows   (LEAST k. k  {t. hamlet ((Rep_run r) t c)})
              = f (LEAST k. k  {t. hamlet ((Rep_run sub) t c)})
          (is (LEAST k. k  ?R) = f (LEAST k. k  ?S))
proof -
  from assms(2) have x. x  ?S by simp
  hence least:x  ?S. y  ?S. x  y
    using Least_nat_ex ..
  from assms(1) have strict_mono f by (simp add: dilating_def dilating_fun_def)
  from Least_strict_mono[OF this least] have
    (LEAST y. y  f ` ?S)  = f (LEAST x. x  ?S) .
  with tick_set_sub[OF assms(1), of c] show ?thesis by auto
qed

text ‹
  If a clock ticks in a run, it ticks in the subrun.
›
lemma ticks_imp_ticks_sub:
  assumes dilating f sub r
  and     k. hamlet ((Rep_run r) k c)
  shows   k0. hamlet ((Rep_run sub) k0 c)
proof -
  from assms(2) obtain k where hamlet ((Rep_run r) k c) by blast
  with ticks_image_sub[OF assms(1)] ticks_sub[OF assms(1)] show ?thesis by blast
qed

text ‹
  Stronger version: it ticks in the subrun and we know when.
›
lemma ticks_imp_ticks_subk:
  assumes dilating f sub r
  and     hamlet ((Rep_run r) k c)
  shows   k0. f k0 = k  hamlet ((Rep_run sub) k0 c)
proof -
  from no_tick_sub[OF assms(1)] assms(2) have k0. f k0 = k by blast
  from this obtain k0 where f k0 = k by blast
  moreover with ticks_sub[OF assms(1)] assms(2)
    have hamlet ((Rep_run sub) k0 c) by blast
  ultimately show ?thesis by blast
qed

text ‹
  A dilating function preserves the tick count on an interval for any clock.
›
lemma dilated_ticks_strict:
  assumes dilating f sub r
  shows   {i. f m < i  i < f n  hamlet ((Rep_run r) i c)}
          = image f {i. m < i  i < n  hamlet ((Rep_run sub) i c)}
    (is ?RUN = image f ?SUB)
proof
  { fix i assume h:i  ?SUB
    hence m < i  i < n by simp
    hence f m < f i  f i < (f n) using assms
      by (simp add: dilating_def dilating_fun_def strict_monoD strict_mono_less_eq)
    moreover from h have hamlet ((Rep_run sub) i c) by simp
    hence hamlet ((Rep_run r) (f i) c) using ticks_sub[OF assms] by blast
    ultimately have f i  ?RUN by simp
  } thus image f ?SUB  ?RUN by blast
next
  { fix i assume h:i  ?RUN
    hence hamlet ((Rep_run r) i c) by simp
    from ticks_imp_ticks_subk[OF assms this]
      obtain i0 where i0prop:f i0 = i  hamlet ((Rep_run sub) i0 c) by blast
    with h have f m < f i0  f i0 < f n by simp
    moreover have strict_mono f using assms dilating_def dilating_fun_def by blast
    ultimately have m < i0  i0 < n
      using strict_mono_less strict_mono_less_eq by blast
    with i0prop have i0. f i0 = i  i0  ?SUB by blast
  } thus ?RUN  image f ?SUB by blast
qed

lemma dilated_ticks_left:
  assumes dilating f sub r
  shows   {i. f m  i  i < f n  hamlet ((Rep_run r) i c)}
          = image f {i. m  i  i < n  hamlet ((Rep_run sub) i c)}
    (is ?RUN = image f ?SUB)
proof
  { fix i assume h:i  ?SUB
    hence m  i  i < n by simp
    hence f m  f i  f i < (f n) using assms
      by (simp add: dilating_def dilating_fun_def strict_monoD strict_mono_less_eq)
    moreover from h have hamlet ((Rep_run sub) i c) by simp
    hence hamlet ((Rep_run r) (f i) c) using ticks_sub[OF assms] by blast
    ultimately have f i  ?RUN by simp
  } thus image f ?SUB  ?RUN by blast
next
  { fix i assume h:i  ?RUN
    hence hamlet ((Rep_run r) i c) by simp
    from ticks_imp_ticks_subk[OF assms this]
      obtain i0 where i0prop:f i0 = i  hamlet ((Rep_run sub) i0 c) by blast
    with h have f m  f i0  f i0 < f n by simp
    moreover have strict_mono f using assms dilating_def dilating_fun_def by blast
    ultimately have m  i0  i0 < n
      using strict_mono_less strict_mono_less_eq by blast
    with i0prop have i0. f i0 = i  i0  ?SUB by blast
  } thus ?RUN  image f ?SUB by blast
qed

lemma dilated_ticks_right:
  assumes dilating f sub r
  shows   {i. f m < i  i  f n  hamlet ((Rep_run r) i c)}
          = image f {i. m < i  i  n  hamlet ((Rep_run sub) i c)}
    (is ?RUN = image f ?SUB)
proof
  { fix i  assume h:i  ?SUB
    hence m < i  i  n by simp
    hence f m < f i  f i  (f n) using assms
      by (simp add: dilating_def dilating_fun_def strict_monoD strict_mono_less_eq)
    moreover from h have hamlet ((Rep_run sub) i c) by simp
    hence hamlet ((Rep_run r) (f i) c) using ticks_sub[OF assms] by blast
    ultimately have f i  ?RUN by simp
  } thus image f ?SUB  ?RUN by blast
next
  { fix i assume h:i  ?RUN
    hence hamlet ((Rep_run r) i c) by simp
    from ticks_imp_ticks_subk[OF assms this]
      obtain i0 where i0prop:f i0 = i  hamlet ((Rep_run sub) i0 c) by blast
    with h have f m < f i0  f i0  f n by simp
    moreover have strict_mono f using assms dilating_def dilating_fun_def by blast
    ultimately have m < i0  i0  n
      using strict_mono_less strict_mono_less_eq by blast
    with i0prop have i0. f i0 = i  i0  ?SUB by blast
  } thus ?RUN  image f ?SUB by blast
qed

lemma dilated_ticks:
  assumes dilating f sub r
  shows   {i. f m  i  i  f n  hamlet ((Rep_run r) i c)}
          = image f {i. m  i  i  n  hamlet ((Rep_run sub) i c)}
    (is ?RUN = image f ?SUB)
proof
  { fix i assume h:i  ?SUB
    hence m  i  i  n by simp
    hence f m  f i  f i  (f n)
      using assms by (simp add: dilating_def dilating_fun_def strict_mono_less_eq)
    moreover from h have hamlet ((Rep_run sub) i c) by simp
    hence hamlet ((Rep_run r) (f i) c) using ticks_sub[OF assms] by blast
    ultimately have f i ?RUN by simp
  } thus image f ?SUB  ?RUN by blast
next
  { fix i assume h:i  ?RUN
    hence hamlet ((Rep_run r) i c) by simp
    from ticks_imp_ticks_subk[OF assms this]
      obtain i0 where i0prop:f i0 = i  hamlet ((Rep_run sub) i0 c) by blast
    with h have f m  f i0  f i0  f n by simp
    moreover have strict_mono f using assms dilating_def dilating_fun_def by blast
    ultimately have m  i0  i0  n using strict_mono_less_eq by blast
    with i0prop have i0. f i0 = i  i0  ?SUB by blast
  } thus ?RUN  image f ?SUB by blast
qed


text ‹
  No tick can occur in a dilated run before the image of 0 by the dilation function.
›

lemma empty_dilated_prefix:
  assumes dilating f sub r
  and     n < f 0
shows   ¬ hamlet ((Rep_run r) n c)
proof -
  from assms have False by (simp add: dilating_def dilating_fun_def)
  thus ?thesis ..
qed

corollary empty_dilated_prefix':
  assumes dilating f sub r
  shows   {i. f 0  i  i  f n  hamlet ((Rep_run r) i c)}
         = {i. i  f n  hamlet ((Rep_run r) i c)}
proof -
  from assms have strict_mono f by (simp add: dilating_def dilating_fun_def)
  hence f 0  f n unfolding strict_mono_def by (simp add: less_mono_imp_le_mono)
  hence i. i  f n = (i < f 0)  (f 0  i  i  f n) by auto
  hence {i. i  f n  hamlet ((Rep_run r) i c)}
        = {i. i < f 0  hamlet ((Rep_run r) i c)}
         {i. f 0  i  i  f n  hamlet ((Rep_run r) i c)}
    by auto
  also have ... = {i. f 0  i  i  f n  hamlet ((Rep_run r) i c)}
     using empty_dilated_prefix[OF assms] by blast
  finally show ?thesis by simp
qed

corollary dilated_prefix:
  assumes dilating f sub r
  shows   {i. i  f n  hamlet ((Rep_run r) i c)}
          = image f {i. i  n  hamlet ((Rep_run sub) i c)}
proof -
  have {i. 0  i  i  f n  hamlet ((Rep_run r) i c)}
        = image f {i. 0  i  i  n  hamlet ((Rep_run sub) i c)}
    using dilated_ticks[OF assms] empty_dilated_prefix'[OF assms] by blast
  thus ?thesis by simp
qed

corollary dilated_strict_prefix:
  assumes dilating f sub r
  shows   {i. i < f n  hamlet ((Rep_run r) i c)}
          = image f {i. i < n  hamlet ((Rep_run sub) i c)}
proof -
  from assms have dil:dilating_fun f r unfolding dilating_def by simp
  from dil have f0:f 0 = 0  using dilating_fun_def by blast
  from dilating_fun_image_left[OF dil, of 0 n c]
  have {i. f 0  i  i < f n  hamlet ((Rep_run r) i c)}
        = image f {i. 0  i  i < n  hamlet ((Rep_run r) (f i) c)} .
  hence {i. i < f n  hamlet ((Rep_run r) i c)}
        = image f {i. i < n  hamlet ((Rep_run r) (f i) c)}
    using f0 by simp
  also have ... = image f {i. i < n  hamlet ((Rep_run sub) i c)}
    using assms dilating_def by blast
  finally show ?thesis by simp
qed

text‹A singleton of @{typ nat} can be defined with a weaker property.› 
lemma nat_sing_prop:
  {i::nat. i = k  P(i)} = {i::nat. i = k  P(k)}
by auto

text ‹
  The set definition and the function definition of @{const tick_count}
  are equivalent.
›
lemma tick_count_is_fun[code]:tick_count r c n = run_tick_count r c n
proof (induction n)
  case 0
    have tick_count r c 0 = card {i. i  0  hamlet ((Rep_run r) i c)}
      by (simp add: tick_count_def)
    also have ... = card {i::nat. i = 0  hamlet ((Rep_run r) 0 c)}
      using le_zero_eq nat_sing_prop[of 0 λi. hamlet ((Rep_run r) i c)] by simp
    also have ... = (if hamlet ((Rep_run r) 0 c) then 1 else 0) by simp
    also have ... = run_tick_count r c 0 by simp
    finally show ?case .
next
  case (Suc k)
    show ?case
    proof (cases hamlet ((Rep_run r) (Suc k) c))
      case True
        hence {i. i  Suc k  hamlet ((Rep_run r) i c)}
             = insert (Suc k) {i. i  k  hamlet ((Rep_run r) i c)} by auto
        hence tick_count r c (Suc k) = Suc (tick_count r c k)
          by (simp add: tick_count_def)
        with Suc.IH have tick_count r c (Suc k) = Suc (run_tick_count r c k) by simp
        thus ?thesis by (simp add: True)
    next
      case False
        hence {i. i  Suc k  hamlet ((Rep_run r) i c)}
             = {i. i  k  hamlet ((Rep_run r) i c)}
          using le_Suc_eq by auto
        hence tick_count r c (Suc k) = tick_count r c k
          by (simp add: tick_count_def)
        thus ?thesis using Suc.IH by (simp add: False)
    qed
qed

text ‹
  To show that the set definition and the function definition 
  of @{const tick_count_strict} are equivalent, we first show that
  the ‹strictness› of @{const tick_count_strict} can be softened using @{const Suc}.
› 
lemma tick_count_strict_suc:tick_count_strict r c (Suc n) = tick_count r c n
  unfolding tick_count_def tick_count_strict_def using less_Suc_eq_le by auto

lemma tick_count_strict_is_fun[code]:
  tick_count_strict r c n = run_tick_count_strictly r c n
proof (cases n = 0)
  case True
    hence tick_count_strict r c n = 0 unfolding tick_count_strict_def by simp
    also have ... = run_tick_count_strictly r c 0
      using run_tick_count_strictly.simps(1)[symmetric] .
    finally show ?thesis using True by simp
next
  case False
    from not0_implies_Suc[OF this] obtain m where *:n = Suc m by blast
    hence tick_count_strict r c n = tick_count r c m
      using tick_count_strict_suc by simp
    also have ... = run_tick_count r c m using tick_count_is_fun[of r c m] .
    also have ... = run_tick_count_strictly r c (Suc m)
      using run_tick_count_strictly.simps(2)[symmetric] .
    finally show ?thesis using * by simp
qed

text ‹
  This leads to an alternate definition of the strict precedence relation.
›
lemma strictly_precedes_alt_def1:
  { ρ. n::nat. (run_tick_count ρ K2 n)  (run_tick_count_strictly ρ K1 n) }
 = { ρ. n::nat. (run_tick_count_strictly ρ K2 (Suc n))
                   (run_tick_count_strictly ρ K1 n) }
by auto

text ‹
  The strict precedence relation can even be defined using 
  only @{construn_tick_count}:
›
lemma zero_gt_all:
  assumes P (0::nat)
      and n. n > 0  P n
    shows P n
  using assms neq0_conv by blast

lemma strictly_precedes_alt_def2:
  { ρ. n::nat. (run_tick_count ρ K2 n)  (run_tick_count_strictly ρ K1 n) }
 = { ρ. (¬hamlet ((Rep_run ρ) 0 K2))
       (n::nat. (run_tick_count ρ K2 (Suc n))  (run_tick_count ρ K1 n)) }
  (is ?P = ?P')
proof
  { fix r::'a run
    assume r  ?P
    hence n::nat. (run_tick_count r K2 n)  (run_tick_count_strictly r K1 n)
      by simp
    hence 1:n::nat. (tick_count r K2 n)  (tick_count_strict r K1 n)
      using tick_count_is_fun[symmetric, of r] tick_count_strict_is_fun[symmetric, of r]
      by simp
    hence n::nat. (tick_count_strict r K2 (Suc n))  (tick_count_strict r K1 n)
      using tick_count_strict_suc[symmetric, of r K2] by simp
    hence n::nat. (tick_count_strict r K2 (Suc (Suc n)))  (tick_count_strict r K1 (Suc n))
      by simp
    hence n::nat. (tick_count r K2 (Suc n))  (tick_count r K1 n)
      using tick_count_strict_suc[symmetric, of r] by simp
    hence *:n::nat. (run_tick_count r K2 (Suc n))  (run_tick_count r K1 n)
      by (simp add: tick_count_is_fun)
    from 1 have tick_count r K2 0 <= tick_count_strict r K1 0 by simp
    moreover have tick_count_strict r K1 0 = 0 unfolding tick_count_strict_def by simp
    ultimately have tick_count r K2 0 = 0 by simp
    hence ¬hamlet ((Rep_run r) 0 K2) unfolding tick_count_def by auto
    with * have r  ?P' by simp
  } thus ?P  ?P' ..
  { fix r::'a run
    assume h:r  ?P'
    hence n::nat. (run_tick_count r K2 (Suc n))  (run_tick_count r K1 n) by simp
    hence n::nat. (tick_count r K2 (Suc n))  (tick_count r K1 n)
      by (simp add: tick_count_is_fun) 
    hence n::nat. (tick_count r K2 (Suc n))  (tick_count_strict r K1 (Suc n))
      using tick_count_strict_suc[symmetric, of r K1] by simp
    hence *:n. n > 0  (tick_count r K2 n)  (tick_count_strict r K1 n)
      using gr0_implies_Suc by blast
    have tick_count_strict r K1 0 = 0 unfolding tick_count_strict_def by simp
    moreover from h have ¬hamlet ((Rep_run r) 0 K2) by simp
    hence tick_count r K2 0 = 0 unfolding tick_count_def by auto
    ultimately have tick_count r K2 0  tick_count_strict r K1 0 by simp
    from zero_gt_all[of λn. tick_count r K2 n  tick_count_strict r K1 n, OF this ] *
      have n. (tick_count r K2 n)  (tick_count_strict r K1 n) by simp
    hence n. (run_tick_count r K2 n)  (run_tick_count_strictly r K1 n)
      by (simp add: tick_count_is_fun tick_count_strict_is_fun)
    hence r  ?P ..
  } thus ?P'  ?P ..
qed

text ‹
  Some properties of @{construn_tick_count}, @{consttick_count} 
  and @{constSuc}:
›
lemma run_tick_count_suc:
  run_tick_count r c (Suc n) = (if hamlet ((Rep_run r) (Suc n) c)
                                 then Suc (run_tick_count r c n)
                                 else run_tick_count r c n)
by simp

corollary tick_count_suc:
  tick_count r c (Suc n) = (if hamlet ((Rep_run r) (Suc n) c)
                             then Suc (tick_count r c n)
                             else tick_count r c n)
by (simp add: tick_count_is_fun)

text ‹
  Some generic properties on the cardinal of sets of nat that we will need later.
›
lemma card_suc:
  card {i. i  (Suc n)  P i} = card {i. i  n  P i} + card {i. i = (Suc n)  P i}
proof -
  have {i. i  n  P i}  {i. i = (Suc n)  P i} = {} by auto
  moreover have {i. i  n  P i}  {i. i = (Suc n)  P i}
               = {i. i  (Suc n)  P i} by auto
  moreover have finite {i. i  n  P i} by simp
  moreover have finite {i. i = (Suc n)  P i} by simp
  ultimately show ?thesis
    using card_Un_disjoint[of {i. i  n  P i} {i. i = Suc n  P i}] by simp
qed

lemma card_le_leq:
  assumes m < n
    shows card {i::nat. m < i  i  n  P i}
         = card {i. m < i  i < n  P i} + card {i. i = n  P i}
proof -
  have {i::nat. m < i  i < n  P i}  {i. i = n  P i} = {} by auto
  moreover with assms have
    {i::nat. m < i  i < n  P i}  {i. i = n  P i} = {i. m < i  i  n  P i}
  by auto
  moreover have finite {i. m < i  i < n  P i} by simp
  moreover have finite {i. i = n  P i} by simp
  ultimately show ?thesis
    using card_Un_disjoint[of {i. m < i  i < n  P i} {i. i = n  P i}] by simp
qed

lemma card_le_leq_0:
  card {i::nat. i  n  P i} = card {i. i < n  P i} + card {i. i = n  P i}
proof -
  have {i::nat. i < n  P i}  {i. i = n  P i} = {} by auto
  moreover have {i. i < n  P i}  {i. i = n  P i} = {i. i  n  P i} by auto
  moreover have finite {i. i < n  P i} by simp
  moreover have finite {i. i = n  P i} by simp
  ultimately show ?thesis
    using card_Un_disjoint[of {i. i < n  P i} {i. i = n  P i}] by simp
qed

lemma card_mnm:
  assumes m < n
    shows card {i::nat. i < n  P i}
         = card {i. i  m  P i} + card {i. m < i  i < n  P i}
proof -
  have 1:{i::nat. i  m  P i}  {i. m < i  i < n  P i} = {} by auto
  from assms have i::nat. i < n = (i  m)  (m < i  i < n)
    using less_trans by auto
  hence 2:
    {i::nat. i < n  P i} = {i. i  m  P i}  {i. m < i  i < n  P i} by blast
  have 3:finite {i. i  m  P i} by simp
  have 4:finite {i. m < i  i < n  P i} by simp
  from card_Un_disjoint[OF 3 4 1] 2 show ?thesis by simp
qed

lemma card_mnm':
  assumes m < n
    shows card {i::nat. i < n  P i}
         = card {i. i < m  P i} + card {i. m  i  i < n  P i}
proof -
  have 1:{i::nat. i < m  P i}  {i. m  i  i < n  P i} = {} by auto
  from assms have i::nat. i < n = (i < m)  (m  i  i < n)
    using less_trans by auto
  hence 2:
    {i::nat. i < n  P i} = {i. i < m  P i}  {i. m  i  i < n  P i} by blast
  have 3:finite {i. i < m  P i} by simp
  have 4:finite {i. m  i  i < n  P i} by simp
  from card_Un_disjoint[OF 3 4 1] 2 show ?thesis by simp
qed

lemma nat_interval_union:
  assumes m  n
    shows {i::nat. i  n  P i}
         = {i::nat. i  m  P i}  {i::nat. m < i  i  n  P i}
using assms le_cases nat_less_le by auto

lemma card_sing_prop:card {i. i = n  P i} = (if P n then 1 else 0)
proof (cases P n)
  case True
    hence {i. i = n  P i} = {n} by (simp add: Collect_conv_if)
    with P n show ?thesis by simp
next
  case False
    hence {i. i = n  P i} = {} by (simp add: Collect_conv_if)
    with ¬P n show ?thesis by simp
qed

lemma card_prop_mono:
  assumes m  n
    shows card {i::nat. i  m  P i}  card {i. i  n  P i}
proof -
  from assms have {i. i  m  P i}  {i. i  n  P i} by auto
  moreover have finite {i. i  n  P i} by simp
  ultimately show ?thesis by (simp add: card_mono)
qed


text ‹
  In a dilated run, no tick occurs strictly between two successive instants that 
  are the images by @{term f} of instants of the original run.
›
lemma no_tick_before_suc:
  assumes dilating f sub r
      and (f n) < k  k < (f (Suc n))
    shows ¬hamlet ((Rep_run r) k c)
proof -
  from assms(1) have smf:strict_mono f by (simp add: dilating_def dilating_fun_def)
  { fix k assume h:f n < k  k < f (Suc n)  hamlet ((Rep_run r) k c)
    hence k0. f k0 = k using assms(1) dilating_def dilating_fun_def by blast
    from this obtain k0 where f k0 = k by blast
    with h have f n < f k0  f k0 < f (Suc n) by simp
    hence False using smf not_less_eq strict_mono_less by blast
  } thus ?thesis using assms(2) by blast
qed

text ‹
  From this, we show that the number of ticks on any clock at @{term f (Suc n)}
  depends only on the number of ticks on this clock at @{term f n} and whether
  this clock ticks at @{term f (Suc n)}.
  All the instants in between are stuttering instants.
›
lemma tick_count_fsuc:
  assumes dilating f sub r
    shows tick_count r c (f (Suc n))
         = tick_count r c (f n) + card {k. k = f (Suc n)  hamlet ((Rep_run r) k c)}
proof -
  have smf:strict_mono f using assms dilating_def dilating_fun_def by blast
  moreover have finite {k. k  f n  hamlet ((Rep_run r) k c)} by simp
  moreover have *:finite {k. f n < k  k  f (Suc n)  hamlet ((Rep_run r) k c)} by simp
  ultimately have {k. k  f (Suc n)  hamlet ((Rep_run r) k c)} =
                        {k. k  f n  hamlet ((Rep_run r) k c)}
                       {k. f n < k  k  f (Suc n)  hamlet ((Rep_run r) k c)}
    by (simp add: nat_interval_union strict_mono_less_eq)
  moreover have {k. k  f n  hamlet ((Rep_run r) k c)}
                   {k. f n < k  k  f (Suc n)  hamlet ((Rep_run r) k c)} = {}
     by auto
  ultimately have card {k. k  f (Suc n)  hamlet (Rep_run r k c)} =
                      card {k. k  f n  hamlet (Rep_run r k c)}
                    + card {k. f n < k  k  f (Suc n)  hamlet (Rep_run r k c)}
    by (simp add: * card_Un_disjoint)
  moreover from no_tick_before_suc[OF assms] have
    {k. f n < k  k  f (Suc n)  hamlet ((Rep_run r) k c)} =
            {k. k = f (Suc n)  hamlet ((Rep_run r) k c)}
    using smf strict_mono_less by fastforce
  ultimately show ?thesis by (simp add: tick_count_def)
qed

corollary tick_count_f_suc:
  assumes dilating f sub r
    shows tick_count r c (f (Suc n))
         = tick_count r c (f n) + (if hamlet ((Rep_run r) (f (Suc n)) c) then 1 else 0)
using tick_count_fsuc[OF assms]
      card_sing_prop[of f (Suc n) λk. hamlet ((Rep_run r) k c)] by simp

corollary tick_count_f_suc_suc:
  assumes dilating f sub r
    shows tick_count r c (f (Suc n)) = (if hamlet ((Rep_run r) (f (Suc n)) c)
                                         then Suc (tick_count r c (f n))
                                         else tick_count r c (f n))
using tick_count_f_suc[OF assms] by simp

lemma tick_count_f_suc_sub:
  assumes dilating f sub r
    shows tick_count r c (f (Suc n)) = (if hamlet ((Rep_run sub) (Suc n) c)
                                         then Suc (tick_count r c (f n))
                                         else tick_count r c (f n))
using tick_count_f_suc_suc[OF assms] assms by (simp add: dilating_def)

text ‹
  The number of ticks does not progress during stuttering instants.
›
lemma tick_count_latest:
  assumes dilating f sub r
      and f np < n  (k. f np < k  k  n  (k0. f k0 = k))
    shows tick_count r c n = tick_count r c (f np)
proof -
  have union:{i. i  n  hamlet ((Rep_run r) i c)} =
          {i. i  f np  hamlet ((Rep_run r) i c)}
         {i. f np < i  i  n  hamlet ((Rep_run r) i c)} using assms(2) by auto
  have partition: {i. i  f np  hamlet ((Rep_run r) i c)}
         {i. f np < i  i  n  hamlet ((Rep_run r) i c)} = {}
    by (simp add: disjoint_iff_not_equal)
  from assms have {i. f np < i  i  n  hamlet ((Rep_run r) i c)} = {}
    using no_tick_sub by fastforce
  with union and partition show ?thesis by (simp add: tick_count_def)
qed

text ‹
  We finally show that the number of ticks on any clock is preserved by dilation.
›
lemma tick_count_sub:
  assumes dilating f sub r
    shows tick_count sub c n = tick_count r c (f n)
proof -
  have tick_count sub c n = card {i. i  n  hamlet ((Rep_run sub) i c)}
    using tick_count_def[of sub c n] .
  also have ... = card (image f {i. i  n  hamlet ((Rep_run sub) i c)})
    using assms dilating_def dilating_injects[OF assms] by (simp add: card_image)
  also have ... = card {i. i  f n  hamlet ((Rep_run r) i c)}
    using dilated_prefix[OF assms, symmetric, of n c] by simp
  also have ... = tick_count r c (f n)
    using tick_count_def[of r c f n] by simp
  finally show ?thesis .
qed

corollary run_tick_count_sub:
  assumes dilating f sub r
    shows run_tick_count sub c n = run_tick_count r c (f n)
proof -
  have run_tick_count sub c n = tick_count sub c n
    using tick_count_is_fun[of sub c n, symmetric] .
  also from tick_count_sub[OF assms] have ... = tick_count r c (f n) .
  also have ... = # r c (f n) using tick_count_is_fun[of r c f n] .
  finally show ?thesis .
qed

text ‹
  The number of ticks occurring strictly before the first instant is null.
›
lemma tick_count_strict_0:
  assumes dilating f sub r
    shows tick_count_strict r c (f 0) = 0
proof -
  from assms have f 0 = 0 by (simp add: dilating_def dilating_fun_def)
  thus ?thesis unfolding tick_count_strict_def by simp
qed

text ‹
  The number of ticks strictly before an instant does not progress
  during stuttering instants.
›
lemma tick_count_strict_stable:
  assumes dilating f sub r
  assumes (f n) < k  k < (f (Suc n))
  shows tick_count_strict r c k = tick_count_strict r c (f (Suc n))
proof -
  from assms(1) have smf:strict_mono f by (simp add: dilating_def dilating_fun_def)
  from assms(2) have f n < k by simp
  hence i. k  i  f n < i by simp
  with no_tick_before_suc[OF assms(1)] have
    *:i. k  i  i < f (Suc n)  ¬hamlet ((Rep_run r) i c) by blast
  from tick_count_strict_def have
    tick_count_strict r c (f (Suc n)) = card {i. i < f (Suc n)  hamlet ((Rep_run r) i c)} .
  also have
    ... = card {i. i < k  hamlet ((Rep_run r) i c)}
         + card {i. k  i  i < f (Suc n)  hamlet ((Rep_run r) i c)} 
    using card_mnm' assms(2) by simp
  also have ... = card {i. i < k  hamlet ((Rep_run r) i c)} using * by simp
  finally show ?thesis by (simp add: tick_count_strict_def)
qed

text ‹
  Finally, the number of ticks strictly before an instant is preserved by dilation.
›
lemma tick_count_strict_sub:
  assumes dilating f sub r
    shows tick_count_strict sub c n = tick_count_strict r c (f n)
proof -
  have tick_count_strict sub c n = card {i. i < n  hamlet ((Rep_run sub) i c)}
    using tick_count_strict_def[of sub c n] .
  also have ... = card (image f {i. i < n  hamlet ((Rep_run sub) i c)})
    using assms dilating_def dilating_injects[OF assms] by (simp add: card_image)
  also have ... = card {i. i < f n  hamlet ((Rep_run r) i c)}
    using dilated_strict_prefix[OF assms, symmetric, of n c] by simp
  also have ... = tick_count_strict r c (f n)
    using tick_count_strict_def[of r c f n] by simp
  finally show ?thesis .
qed

text ‹
  The tick count on any clock can only increase.
›

lemma mono_tick_count:
  mono (λ k. tick_count r c k)
proof
  { fix x y::nat
    assume x  y
    from card_prop_mono[OF this] have tick_count r c x  tick_count r c y
      unfolding tick_count_def by simp
  } thus x y. x  y  tick_count r c x  tick_count r c y .
qed

text ‹
  In a dilated run, for any stuttering instant, there is an instant which is the 
  image of an instant in the original run, and which is the latest one before
  the stuttering instant.
›
lemma greatest_prev_image:
  assumes dilating f sub r
    shows (n0. f n0 = n)  (np. f np < n  (k. f np < k  k  n  (k0. f k0 = k)))
proof (induction n)
  case 0
    with assms have f 0 = 0 by (simp add: dilating_def dilating_fun_def)
    thus ?case using "0.prems" by blast
next
  case (Suc n)
  show ?case
  proof (cases n0. f n0 = n)
    case True
      from this obtain n0 where f n0 = n by blast
      hence f n0 < (Suc n)  (k. f n0 < k  k  (Suc n)  (k0. f k0 = k))
        using Suc.prems Suc_leI le_antisym by blast
      thus ?thesis by blast
  next
    case False
    from Suc.IH[OF this] obtain np
      where f np < n  (k. f np < k  k  n  (k0. f k0 = k)) by blast
    hence f np < Suc n  (k. f np < k  k  n  (k0. f k0 = k)) by simp
    with Suc(2) have f np < (Suc n)  (k. f np < k  k  (Suc n)  (k0. f k0 = k))
      using le_Suc_eq by auto
    thus ?thesis by blast
  qed
qed

text ‹
  If a strictly monotonous function on @{typ nat} increases only by one,
  its argument was increased only by one.
›
lemma strict_mono_suc:
  assumes strict_mono f
      and f sn = Suc (f n)
    shows sn = Suc n
proof -
  from assms(2) have f sn > f n by simp
  with strict_mono_less[OF assms(1)] have sn > n by simp
  moreover have sn  Suc n
  proof -
    { assume sn > Suc n
      from this obtain i where n < i  i < sn by blast
      hence f n < f i  f i < f sn using assms(1) by (simp add: strict_mono_def)
      with assms(2) have False by simp
    } thus ?thesis using not_less by blast
  qed
  ultimately show ?thesis by (simp add: Suc_leI)
qed

text ‹
  Two successive non stuttering instants of a dilated run are the images
  of two successive instants of the original run.
›
lemma next_non_stuttering:
  assumes dilating f sub r
      and f np < n  (k. f np < k  k  n  (k0. f k0 = k))
      and f sn0 = Suc n
    shows sn0 = Suc np
proof -
  from assms(1) have smf:strict_mono f by (simp add: dilating_def dilating_fun_def)
  from assms(2) have *:k. f np < k  k < Suc n  (k0. f k0 = k) by simp
  from assms(2) have f np < n by simp
  with smf assms(3) have **:sn0 > np using strict_mono_less by fastforce
  have Suc n  f (Suc np)
  proof -
    { assume h:Suc n > f (Suc np)
      hence Suc np < sn0 using ** Suc_lessI assms(3) by fastforce
      hence k. k > np  f k < Suc n using h by blast
      with * have False using smf strict_mono_less by blast
    } thus ?thesis using not_less by blast
  qed
  hence sn0  Suc np using assms(3) smf using strict_mono_less_eq by fastforce
  with ** show ?thesis by simp
qed

text ‹
  The order relation between tick counts on clocks is preserved by dilation.
›
lemma dil_tick_count:
  assumes sub  r
      and n. run_tick_count sub a n  run_tick_count sub b n
    shows run_tick_count r a n  run_tick_count r b n
proof -
  from assms(1) is_subrun_def obtain f where *:dilating f sub r by blast
  show ?thesis
  proof (induction n)
    case 0 
      from assms(2) have run_tick_count sub a 0  run_tick_count sub b 0 ..
      with run_tick_count_sub[OF *, of _ 0] have
        run_tick_count r a (f 0)  run_tick_count r b (f 0) by simp
      moreover from * have f 0 = 0 by (simp add:dilating_def dilating_fun_def)
      ultimately show ?case by simp
  next
    case (Suc n') thus ?case 
    proof (cases n0. f n0 = Suc n')
      case True
        from this obtain n0 where fn0:f n0 = Suc n' by blast
        show ?thesis
        proof (cases hamlet ((Rep_run sub) n0 a))
          case True
            have run_tick_count r a (f n0)  run_tick_count r b (f n0)
              using assms(2) run_tick_count_sub[OF *] by simp
            thus ?thesis by (simp add: fn0)
        next
          case False
            hence ¬ hamlet ((Rep_run r) (Suc n') a)
              using * fn0 ticks_sub by fastforce
            thus ?thesis by (simp add: Suc.IH le_SucI)
        qed
    next
      case False
        thus ?thesis  using * Suc.IH no_tick_sub by fastforce
    qed
  qed
qed

text ‹
  Time does not progress during stuttering instants.
›
lemma stutter_no_time:
  assumes dilating f sub r
      and k. f n < k  k  m  (k0. f k0 = k)
      and m > f n
    shows time ((Rep_run r) m c) = time ((Rep_run r) (f n) c)
proof -
  from assms have k. k < m - (f n)  (k0. f k0 = Suc ((f n) + k)) by simp
  hence k. k < m - (f n)
             time ((Rep_run r) (Suc ((f n) + k)) c) = time ((Rep_run r) ((f n) + k) c)
    using assms(1) by (simp add: dilating_def dilating_fun_def)
  hence *:k. k < m - (f n)  time ((Rep_run r) (Suc ((f n) + k)) c) = time ((Rep_run r) (f n) c)
    using bounded_suc_ind[of m - (f n) λk. time (Rep_run r k c) f n] by blast
  from assms(3) obtain m0 where m0:Suc m0 = m - (f n) using Suc_diff_Suc by blast
  with * have time ((Rep_run r) (Suc ((f n) + m0)) c) = time ((Rep_run r) (f n) c) by auto
  moreover from m0 have Suc ((f n) + m0) = m by simp
  ultimately show ?thesis by simp
qed

lemma time_stuttering:
  assumes dilating f sub r
      and time ((Rep_run sub) n c) = τ
      and k. f n < k  k  m  (k0. f k0 = k)
      and m > f n
    shows time ((Rep_run r) m c) = τ
proof -
  from assms(3) have time ((Rep_run r) m c) = time ((Rep_run r) (f n) c)
    using  stutter_no_time[OF assms(1,3,4)] by blast
  also from assms(1,2) have time ((Rep_run r) (f n) c) = τ by (simp add: dilating_def)
  finally show ?thesis .
qed

text ‹
  The first instant at which a given date is reached on a clock is preserved
  by dilation.
›
lemma first_time_image:
  assumes dilating f sub r
    shows first_time sub c n t = first_time r c (f n) t
proof
  assume first_time sub c n t
  with before_first_time[OF this]
    have *:time ((Rep_run sub) n c) = t  (m < n. time((Rep_run sub) m c) < t)
      by (simp add: first_time_def)
  moreover have n c. time (Rep_run sub n c) = time (Rep_run r (f n) c)
      using assms(1) by (simp add: dilating_def)
  ultimately have **:
    time ((Rep_run r) (f n) c) = t  (m < n. time((Rep_run r) (f m) c) < t)
    by simp
  have m < f n. time ((Rep_run r) m c) < t
  proof -
  { fix m assume hyp:m < f n
    have time ((Rep_run r) m c) < t
    proof (cases m0. f m0 = m)
      case True
        from this obtain m0 where mm0:m = f m0 by blast
        with hyp have m0n:m0 < n using assms(1)
          by (simp add: dilating_def dilating_fun_def strict_mono_less)
        hence time ((Rep_run sub) m0 c) < t using * by blast
        thus ?thesis by (simp add: mm0 m0n **)
    next
      case False
        hence mp. f mp < m  (k. f mp < k  k  m  (k0. f k0 = k))
          using greatest_prev_image[OF assms] by simp
        from this obtain mp where
          mp:f mp < m  (k. f mp < k  k  m  (k0. f k0 = k)) by blast
        hence time ((Rep_run r) m c) = time ((Rep_run sub) mp c)
          using time_stuttering[OF assms] by blast
        also from hyp mp have f mp < f n by linarith
        hence mp < n using assms
          by (simp add:dilating_def dilating_fun_def strict_mono_less)
        hence time ((Rep_run sub) mp c) < t using * by simp
        finally show ?thesis by simp
      qed
    } thus ?thesis by simp
  qed
  with ** show first_time r c (f n) t by (simp add: alt_first_time_def)
next
  assume first_time r c (f n) t
  hence *:time ((Rep_run r) (f n) c) = t  (k < f n. time ((Rep_run r) k c) < t)
    by (simp add: first_time_def before_first_time)
  hence time ((Rep_run sub) n c) = t using assms dilating_def by blast
  moreover from * have (k < n. time ((Rep_run sub) k c) < t)
    using assms dilating_def dilating_fun_def strict_monoD by fastforce
  ultimately show first_time sub c n t by (simp add: alt_first_time_def)
qed

text ‹
  The first instant of a dilated run is necessarily the image of the first instant
  of the original run.
›
lemma first_dilated_instant:
  assumes strict_mono f
      and f (0::nat) = (0::nat)
    shows Max {i. f i  0} = 0
proof -
  from assms(2) have n > 0. f n > 0 using strict_monoD[OF assms(1)] by force
  hence n  0. ¬(f n  0) by simp
  with assms(2) have {i. f i  0} = {0} by blast
  thus ?thesis by simp
qed

text ‹
  For any instant @{term n} of a dilated run, let @{term n0} be the last 
  instant before @{term n} that is the image of an original instant. All instants
  strictly after @{term n0} and before @{term n} are stuttering instants.
›
lemma not_image_stut:
  assumes dilating f sub r
      and n0 = Max {i. f i  n}
      and f n0 < k  k  n
    shows k0. f k0 = k
proof -
  from assms(1) have smf:strict_mono f
                and fxge:x. f x  x
    by (auto simp add: dilating_def dilating_fun_def)
  have finite_prefix:finite {i. f i  n} by (simp add: finite_less_ub fxge)
  from assms(1) have f 0  n by (simp add: dilating_def dilating_fun_def)
  hence {i. f i  n}  {} by blast
  from assms(3) fxge have f n0 < n by linarith
  from assms(2) have x > n0. f x > n using Max.coboundedI[OF finite_prefix]
    using not_le by auto
  with assms(3) strict_mono_less[OF smf] show ?thesis by auto
qed

text ‹
  For any dilating function @{term f}, @{term dil_inverse f} is a 
  contracting function.
›
lemma contracting_inverse:
  assumes dilating f sub r
    shows contracting (dil_inverse f) r sub f
proof -
  from assms have smf:strict_mono f
    and no_img_tick:k. (k0. f k0 = k)  (c. ¬(hamlet ((Rep_run r) k c)))
    and no_img_time:n. (n0. f n0 = (Suc n))
                           (c. time ((Rep_run r) (Suc n) c) = time ((Rep_run r) n c))
    and fxge:x. f x  x and f0n:n. f 0  n and f0:f 0 = 0
    by (auto simp add: dilating_def dilating_fun_def)
  have finite_prefix:n. finite {i. f i  n} by (auto simp add: finite_less_ub fxge)
  have prefix_not_empty:n. {i. f i  n}  {} using f0n by blast                

  have 1:mono (dil_inverse f)
  proof -
  { fix x::nat and y::nat assume hyp:x  y
    hence inc:{i. f i  x}  {i. f i  y}
      by (simp add: hyp Collect_mono le_trans)
    from Max_mono[OF inc prefix_not_empty finite_prefix]
      have (dil_inverse f) x  (dil_inverse f) y unfolding dil_inverse_def .
  } thus ?thesis unfolding mono_def by simp
  qed

  from first_dilated_instant[OF smf f0] have 2:(dil_inverse f) 0 = 0
    unfolding dil_inverse_def .

  from fxge have n i. f i  n  i  n using le_trans by blast
  hence 3:n. (dil_inverse f) n  n using Max_in[OF finite_prefix prefix_not_empty] 
    unfolding dil_inverse_def by blast

  from 1 2 3 have *:contracting_fun (dil_inverse f) by (simp add: contracting_fun_def)
  
  have n. finite {i. f i  n} by (simp add: finite_prefix)
  moreover have n. {i. f i  n}  {} using prefix_not_empty by blast
  ultimately have 4:n. f ((dil_inverse f) n)  n 
    unfolding dil_inverse_def
    using assms(1) dilating_def dilating_fun_def Max_in by blast

  have 5:n c k. f ((dil_inverse f) n) < k  k  n
                               ¬ hamlet ((Rep_run r) k c)
    using not_image_stut[OF assms] no_img_tick unfolding dil_inverse_def by blast

  have 6:(n c k. f ((dil_inverse f) n)  k  k  n
                       time ((Rep_run r) k c) = time ((Rep_run sub) ((dil_inverse f) n) c))
  proof -
    { fix n c k assume h:f ((dil_inverse f) n)  k  k  n
      let  = time (Rep_run sub ((dil_inverse f) n) c)
      have tau:time (Rep_run sub ((dil_inverse f) n) c) =  ..
      have gn:(dil_inverse f) n = Max {i. f i  n} unfolding dil_inverse_def ..
      from time_stuttering[OF assms tau, of k] not_image_stut[OF assms gn]
      have time ((Rep_run r) k c) = time ((Rep_run sub) ((dil_inverse f) n) c)
      proof (cases f ((dil_inverse f) n) = k)
        case True
          moreover have n c. time (Rep_run sub n c) = time (Rep_run r (f n) c)
            using assms by (simp add: dilating_def)
          ultimately show ?thesis by simp
      next
        case False
          with h have f (Max {i. f i  n}) < k  k  n by (simp add: dil_inverse_def)
          with time_stuttering[OF assms tau, of k] not_image_stut[OF assms gn]
            show ?thesis unfolding dil_inverse_def by auto
      qed
    } thus ?thesis by simp
  qed

  from * 4 5 6 show ?thesis unfolding contracting_def by simp
qed

text ‹
  The only possible contracting function toward a dense run (a run with no empty 
  instants) is the inverse of the dilating function as defined by 
  @{term dil_inverse}.
›
lemma dense_run_dil_inverse_only:
  assumes dilating f sub r
      and contracting g r sub f
      and dense_run sub
    shows g = (dil_inverse f)
proof
  from assms(1) have *:n. finite {i. f i  n}
    using finite_less_ub by (simp add:  dilating_def dilating_fun_def)
  from assms(1) have f 0 = 0 by (simp add:  dilating_def dilating_fun_def)
  hence n. 0  {i. f i  n} by simp
  hence **:n. {i. f i  n}  {} by blast
  { fix n assume h:g n < (dil_inverse f) n
    hence k > g n. f k  n unfolding dil_inverse_def using Max_in[OF * **] by blast
    from this obtain k where kprop:g n < k  f k  n by blast
    with assms(3) dense_run_def obtain c where hamlet ((Rep_run sub) k c) by blast
    hence hamlet ((Rep_run r) (f k) c) using ticks_sub[OF assms(1)] by blast
    moreover from kprop have f (g n) < f k  f k  n using assms(1)
      by (simp add: dilating_def dilating_fun_def strict_monoD)
    ultimately have False using assms(2) unfolding contracting_def by blast
  } hence 1:n. ¬(g n < (dil_inverse f) n) by blast
  { fix n assume h:g n > (dil_inverse f) n
    have k  g n. f k > n 
    proof -
      { assume k  g n. f k  n
        with h have False unfolding dil_inverse_def
        using Max_gr_iff[OF * **] by blast
      }
      thus ?thesis using not_less by blast
    qed
    from this obtain k where k  g n  f k > n by blast
    hence f (g n)  f k  f k > n using assms(1)
      by (simp add: dilating_def dilating_fun_def strict_mono_less_eq)
    hence f (g n) > n by simp
    with assms(2) have False unfolding contracting_def by (simp add: leD)
  } hence 2:n. ¬(g n > (dil_inverse f) n) by blast
  from 1 2 show n. g n = (dil_inverse f) n by (simp add: not_less_iff_gr_or_eq)
qed

end