Theory Temporal

theory Temporal imports Main
begin
  section‹Linear Temporal Logic›
  text‹
    In this section we introduce an algebraic axiomatization of Linear Temporal Logic (LTL).
    We model LTL formulas semantically as predicates on traces. For example the LTL formula
    $\alpha = \Box\; \diamondsuit\; (x = 1)$ is modeled as a predicate 
    $\alpha : (nat \Rightarrow nat) \Rightarrow bool$, where 
    $\alpha \;x = True$ if $x\;i=1$ for infinitely many $i:nat$. In this formula $\Box$
    and $\diamondsuit$ denote the always and eventually operators, respectively. 
    Formulas with multiple variables are modeled similarly. For example a formula $\alpha$ in two 
    variables is modeled as $\alpha : (nat \Rightarrow \tv a) \Rightarrow (nat \Rightarrow \tv b) \Rightarrow bool$,
    and for example $(\Box\; \alpha) \; x\; y$ is defined as $(\forall i . \alpha \; x[i..]\; y[i..])$,
    where $x[i..]\;j = x\;(i+j)$. We would like to construct an algebraic structure (Isabelle class) 
    which has the temporal operators as operations, and which has instatiations to 
    $(nat \Rightarrow \tv a) \Rightarrow bool$, $(nat \Rightarrow \tv a) \Rightarrow (nat \Rightarrow \tv b) \Rightarrow bool$,
    and so on. Ideally our structure should be such that if we have this structure on a type $\tv a::temporal$,
    then we could extend it to $(nat \Rightarrow \tv b) \Rightarrow \tv a$ in a way similar to the
    way Boolean algebras are extended from a type $\tv a::boolean\_algebra$ to $\tv b\Rightarrow \tv a$.
    Unfortunately, if we use for example $\Box$ as primitive operation on our temporal structure,
    then we cannot extend $\Box$ from $\tv a::temporal$ to $(nat \Rightarrow \tv b) \Rightarrow \tv a$. A
    possible extension of $\Box$ could be
      $$(\Box\; \alpha)\;x = \bigwedge_{i:nat} \Box (\alpha\; x[i..]) \mbox{ and } \Box \; b = b$$
    where $\alpha: (nat \Rightarrow \tv b) \Rightarrow \tv a$ and $b:bool$. However, if we apply this
    definition to $\alpha : (nat \Rightarrow \tv a) \Rightarrow (nat \Rightarrow \tv b) \Rightarrow bool$,
    then we get
      $$(\Box\; \alpha) \; x\; y = (\forall i\;j. \alpha \; x[i..]\; y[j..])$$
    which is not correct.

    To evercome this problem we introduce as a primitive operation $!!:\tv a \Rightarrow nat \Rightarrow \tv a$,
    where $\tv a$ is the type of temporal formulas, and $\alpha !! i$ is the formula $\alpha$ at time point $i$.
    If $\alpha$ is a formula in two variables as before, then
      $$(\alpha !! i)\; x\;y = \alpha\; x[i..]\;y[i..].$$
    and we define for example the the operator always by
      $$\Box \alpha = \bigwedge_{i:nat} \alpha !! i$$
›
  notation
    bot ("") and
    top ("") and
    inf (infixl "" 70)
    and sup (infixl "" 65)

  class temporal = complete_boolean_algebra +
    fixes at :: "'a  nat  'a" (infixl "!!" 150)
    assumes [simp]: "a !! i !! j = a !! (i + j)"
    assumes [simp]: "a !! 0 = a"
    assumes [simp]: " !! i = "
    assumes [simp]: "-(a !! i) = (-a) !! i"
    assumes [simp]: "(a  b) !! i = (a !! i)  (b !! i)"
    begin
      definition always :: "'a  'a"  (" (_)" [900] 900) where
        " p = (INF i . p !! i)"

      definition eventually :: "'a  'a"  (" (_)" [900] 900) where
        " p = (SUP i . p !! i)"

      definition "next" :: "'a  'a"  (" (_)" [900] 900) where
        " p = p !! (Suc 0)"

      definition until :: "'a  'a  'a" (infix "until" 65) where 
        "(p until q) = (SUP n . (Inf (at p ` {i . i < n}))  (q !! n))"
    end

text‹
Next lemma, in the context of complete boolean algebras, will be used 
to prove $-(p\ until\ -p) = \Box\; p$.
›
  context complete_boolean_algebra
    begin
      lemma until_always: "(INF n. (SUP i  {i. i < n} . - p i)  ((p :: nat  'a) n))  p n"
        proof -
          have "(INF n. (SUP i{i. i < n}. - p i)  p n)  (INF i{i. i  n}. p i)"
            proof (induction n)
              have "(INF n. (SUP i{i. i < n}. - p i)  p n)  (SUP i{i. i < 0}. - p i)  p 0"
                by (rule INF_lower, simp)
              also have "...  (INF i{i. i  0}. p i)"
                by simp
              finally show "(INF n. (SUP i{i. i < n}. - p i)  p n)  (INF i{i. i  0}. p i)"
                by simp
            next
              fix n::nat assume "(INF n. (SUP i{i. i < n}. - p i)  p n)  (INF i  {i. i  n}. p i)"
              also have " i . i  n  ...  p i" by (rule INF_lower, simp)
              finally have [simp]: " i . i  n  (INF n. (SUP i{i. i < n}. - p i)  p n)  p i"
                by simp
              show "(INF n. (SUP i{i. i < n}. - p i)  p n)  (INF i  {i. i  Suc n}. p i)"
                proof (rule INF_greatest, safe, cases)
                  fix i::nat
                    assume "i  n" from this show "(INF n. (SUP i{i. i < n}. - p i)  p n)  p i" by simp
                next
                  fix i::nat
                    have A: "{i. i  n} = {i . i < Suc n}" by auto
                    have B: "(SUP i{i. i  n}. - p i)  - (INF n. (SUP i{i. i < n}. - p i)  p n)"
                      by (metis (lifting, mono_tags) (INF n. (SUP i{i. i < n}. - p i)  p n)  (INF i{i. i  n}. p i) compl_mono uminus_INF)
                    assume "i  Suc n" and "¬ i  n"
                    from this have [simp]: "i = Suc n" by simp
                    have "(INF n. (SUP i{i. i < n}. - p i)  p n)  (INF n. (SUP i{i. i < n}. - p i)  p n)  ((SUP i{i. i  n}. - p i)  p (Suc n))"
                      by (simp add: A, rule INF_lower, simp)
                    also have "...  ((INF n. (SUP i{i. i < n}. - p i)  p n)  ((- (INF n. (SUP i{i. i < n}. - p i)  p n))  p (Suc n)))"
                      by (rule inf_mono, simp_all, rule_tac y = "- (INF n. (SUP i{i. i < n}. - p i)  p n)" in order_trans, simp_all add: B)
                    also have "...  p i"
                      by (simp add: inf_sup_distrib1 inf_compl_bot)
                    finally show "(INF n. (SUP i{i. i < n}. - p i)  p n)  p i" by simp
                qed
            qed
        also have "(INF i{i. i  n}. p i)  p n" by (rule INF_lower, auto)
        finally show "(INF n. (SUP i  {i. i < n} . - p i)  ((p :: nat  'a) n))  p n" by simp
        qed

     end

text‹
  We prove now a number of results of the temporal class.
›
  context temporal
    begin   
      lemma [simp]: "(a  b) !! i = (a !! i)  (b !! i)"
        by (subst compl_eq_compl_iff [THEN sym], simp)

      lemma always_less [simp]: " p  p"
        proof -
          have " p  p !! 0"
            by (unfold always_def, rule INF_lower, simp)
          also have "p !! 0 = p" by simp
          finally show " p  p" by simp
        qed

      lemma always_and: " (p  q) = ( p)  ( q)"
        by (simp add: always_def INF_inf_distrib)

      lemma eventually_or: " (p  q) = ( p)  ( q)"
        by (simp add: eventually_def SUP_sup_distrib)

      lemma neg_until_always: "-(p until -p) =  p"
        proof (rule order.antisym)
          show "- (p until - p)   p"
           by (simp add: until_def always_def uminus_SUP uminus_INF, rule INF_greatest, cut_tac p = "λ n . p !! n" in until_always, simp)
        next
          have " n .  p  p !! n"
            by (simp add: always_def INF_lower)
          also have " n . p !! n  (SUP x{i. i < n}. (- p) !! x)  p !! n"
            by simp
          finally show " p  -(p until -p)"
            apply (simp add: until_def uminus_SUP uminus_INF)
            by (rule INF_greatest, simp)
        qed

      lemma neg_always_eventually: " p = -  (- p)"
        by (simp add: fun_eq_iff always_def eventually_def until_def uminus_SUP)
        
      lemma neg_true_until_always: "-( until -p) =  p"
        by (simp add: fun_eq_iff always_def until_def uminus_SUP uminus_INF)

      lemma true_until_eventually: "( until p) =  p"
        by (cut_tac p = "-p" in neg_always_eventually, cut_tac p = "-p" in neg_true_until_always, simp)
    end

text‹
  Boolean algebras with $b!!i = b$ form a temporal class.
›

  instantiation bool :: temporal
    begin
      definition at_bool_def [simp]: "(p::bool) !! i = p"
    instance proof 
      qed auto
    end

  type_synonym 'a trace = "nat  'a"

text‹
  Asumming that $\tv a::temporal$ is a type of class $temporal$, and $\tv b$ is an arbitrary type,
  we would like to create the instantiation of $\tv b\ trace \Rightarrow \tv a$ as a temporal
  class. However Isabelle allows only instatiations of functions from a class to another 
  class. To solve this problem we introduce a new class called trace with an operation
  $\mathit{suffix}::\tv a \Rightarrow nat \Rightarrow \tv a$ where 
  $\mathit{suffix}\;a\;i\;j = (a[i..])\; j = a\;(i+j)$ when
  $a$ is a trace with elements of some type $\tv b$ ($\tv a = nat \Rightarrow \tv b$). 
›

  class trace =
    fixes suffix :: "'a  nat  'a" ("_[_ ..]" [80, 15] 80)
    assumes [simp]: "a[i..][j..] = a[i + j..]"
    assumes [simp]: "a[0..] = a"
    begin
      definition "next_trace" :: "'a  'a"  (" (_)" [900] 900) where
        " p = p[Suc 0..]"
    end

  instantiation "fun" :: (trace, temporal) temporal
    begin
      definition at_fun_def: "(P:: 'a  'b) !! i = (λ x . (P (x[i..])) !! i)"
      instance proof qed  (simp_all add: at_fun_def add.commute fun_eq_iff le_fun_def)
    end

text‹
  In the last part of our formalization, we need to instantiate the functions
  from $nat$ to some arbitrary type $\tv a$ as a trace class. However, this again is not
  possible using the instatiation mechanism of Isabelle. We solve this problem
  by creating another class called $nat$, and then we instatiate the functions
  from $\tv a::nat$ to $\tv b$ as traces. The class $nat$ is defined such that if we
  have a type $\tv a::nat$, then $\tv a$ is isomorphic to the type $nat$. 
›

  class nat = zero + plus + minus +
    fixes RepNat :: "'a  nat"
    fixes AbsNat :: "nat  'a"
    assumes [simp]: "RepNat (AbsNat n) = n"
    and [simp]: "AbsNat (RepNat x) = x"
    and zero_Nat_def: "0 = AbsNat 0"
    and plus_Nat_def: "a + b = AbsNat (RepNat a + RepNat b)"
    and minus_Nat_def: "a - b = AbsNat (RepNat a - RepNat b)"
  begin
    lemma AbsNat_plus: "AbsNat (i + j) = AbsNat i + AbsNat j"
      by (simp add: plus_Nat_def)
    lemma AbsNat_zero [simp]: "AbsNat 0 + i = i"
      by (simp add: plus_Nat_def)

    subclass comm_monoid_diff 
      apply (unfold_locales)
        apply (simp_all add: plus_Nat_def zero_Nat_def minus_Nat_def add.assoc)
        by (simp add: add.commute)
  end

text‹
  The type natural numbers is an instantiation of the class $nat$.
›

  instantiation nat :: nat
    begin
      definition RepNat_nat_def [simp]: "(RepNat:: nat  nat) = id"
      definition AbsNat_nat_def [simp]: "(AbsNat:: nat  nat) = id"
      instance proof 
        qed auto
    end

text‹
  Finally, functions from $\tv a::nat$ to some arbitrary type $\tv b$ are instatiated
  as a trace class. 
›

  instantiation "fun" :: (nat, type) trace
    begin
      definition at_trace_def [simp]: "((t :: 'a  'b)[i..]) j = (t  (AbsNat i + j))"
    instance proof
      qed (simp_all add: fun_eq_iff AbsNat_plus add.assoc)
    end

text‹
  By putting together all class definitions and instatiations introduced so far, we obtain the
  temporal class structure for predicates on traces with arbitrary number of parameters.

  For example in the next lemma $r$ and $r'$ are predicate relations, and the operator
  always is available for them as a consequence of the above construction.
›


  lemma "( r) OO ( r')  ( (r OO r'))"
    by (simp add: le_fun_def always_def at_fun_def, auto)

  end