# Theory SubstAx

Up to index of Isabelle/ZF/UNITY

theory SubstAx
imports WFair Constrains
begin

    (*  ID:         $Id: SubstAx.thy,v 1.4 2005/03/28 14:19:58 paulson Exp $
        Author:     Sidi O Ehmety, Computer Laboratory
        Copyright   2001  University of Cambridge

    Theory ported from HOL.
    *)

    header{*Weak LeadsTo relation (restricted to the set of reachable states)*}

    theory SubstAx
    imports WFair Constrains

    begin

    constdefs
      (* The definitions below are not `conventional', but yields simpler rules *)
       Ensures :: "[i,i] => i"            (infixl "Ensures" 60)
        "A Ensures B == {F:program. F : (reachable(F) Int A) ensures (reachable(F) Int B) }"

      LeadsTo :: "[i, i] => i"            (infixl "LeadsTo" 60)
        "A LeadsTo B == {F:program. F:(reachable(F) Int A) leadsTo (reachable(F) Int B)}"

    syntax (xsymbols)
      "LeadsTo" :: "[i, i] => i" (infixl " \<longmapsto>w " 60)

    (*Resembles the previous definition of LeadsTo*)

    (* Equivalence with the HOL-like definition *)
    lemma LeadsTo_eq:
    "st_set(B)==> A LeadsTo B = {F ∈ program. F:(reachable(F) Int A) leadsTo B}"
    apply (unfold LeadsTo_def)
    apply (blast dest: psp_stable2 leadsToD2 constrainsD2 intro: leadsTo_weaken)
    done

    lemma LeadsTo_type: "A LeadsTo B <=program"
    by (unfold LeadsTo_def, auto)

    (*** Specialized laws for handling invariants ***)

    (** Conjoining an Always property **)
    lemma Always_LeadsTo_pre: "F ∈ Always(I) ==> (F:(I Int A) LeadsTo A') <-> (F ∈ A LeadsTo A')"
    by (simp add: LeadsTo_def Always_eq_includes_reachable Int_absorb2 Int_assoc [symmetric] leadsToD2)

    lemma Always_LeadsTo_post: "F ∈ Always(I) ==> (F ∈ A LeadsTo (I Int A')) <-> (F ∈ A LeadsTo A')"
    apply (unfold LeadsTo_def)
    apply (simp add: Always_eq_includes_reachable Int_absorb2 Int_assoc [symmetric] leadsToD2)
    done

    (* Like 'Always_LeadsTo_pre RS iffD1', but with premises in the good order *)
    lemma Always_LeadsToI: "[| F ∈ Always(C); F ∈ (C Int A) LeadsTo A' |] ==> F ∈ A LeadsTo A'"
    by (blast intro: Always_LeadsTo_pre [THEN iffD1])

    (* Like 'Always_LeadsTo_post RS iffD2', but with premises in the good order *)
    lemma Always_LeadsToD: "[| F ∈ Always(C);  F ∈ A LeadsTo A' |] ==> F ∈ A LeadsTo (C Int A')"
    by (blast intro: Always_LeadsTo_post [THEN iffD2])

    (*** Introduction rules ∈ Basis, Trans, Union ***)

    lemma LeadsTo_Basis: "F ∈ A Ensures B ==> F ∈ A LeadsTo B"
    by (auto simp add: Ensures_def LeadsTo_def)

    lemma LeadsTo_Trans:
         "[| F ∈ A LeadsTo B;  F ∈ B LeadsTo C |] ==> F ∈ A LeadsTo C"
    apply (simp (no_asm_use) add: LeadsTo_def)
    apply (blast intro: leadsTo_Trans)
    done

    lemma LeadsTo_Union:
    "[|(!!A. A ∈ S ==> F ∈ A LeadsTo B); F ∈ program|]==>F ∈ Union(S) LeadsTo B"
    apply (simp add: LeadsTo_def)
    apply (subst Int_Union_Union2)
    apply (rule leadsTo_UN, auto)
    done

    (*** Derived rules ***)

    lemma leadsTo_imp_LeadsTo: "F ∈ A leadsTo B ==> F ∈ A LeadsTo B"
    apply (frule leadsToD2, clarify)
    apply (simp (no_asm_simp) add: LeadsTo_eq)
    apply (blast intro: leadsTo_weaken_L)
    done

    (*Useful with cancellation, disjunction*)
    lemma LeadsTo_Un_duplicate: "F ∈ A LeadsTo (A' Un A') ==> F ∈ A LeadsTo A'"
    by (simp add: Un_ac)

    lemma LeadsTo_Un_duplicate2:
         "F ∈ A LeadsTo (A' Un C Un C) ==> F ∈ A LeadsTo (A' Un C)"
    by (simp add: Un_ac)

    lemma LeadsTo_UN:
        "[|(!!i. i ∈ I ==> F ∈ A(i) LeadsTo B); F ∈ program|]
         ==>F:(\<Union>i ∈ I. A(i)) LeadsTo B"
    apply (simp add: LeadsTo_def)
    apply (simp (no_asm_simp) del: UN_simps add: Int_UN_distrib)
    apply (rule leadsTo_UN, auto)
    done

    (*Binary union introduction rule*)
    lemma LeadsTo_Un:
         "[| F ∈ A LeadsTo C; F ∈ B LeadsTo C |] ==> F ∈ (A Un B) LeadsTo C"
    apply (subst Un_eq_Union)
    apply (rule LeadsTo_Union)
    apply (auto dest: LeadsTo_type [THEN subsetD])
    done

    (*Lets us look at the starting state*)
    lemma single_LeadsTo_I:
        "[|(!!s. s ∈ A ==> F:{s} LeadsTo B); F ∈ program|]==>F ∈ A LeadsTo B"
    apply (subst UN_singleton [symmetric], rule LeadsTo_UN, auto)
    done

    lemma subset_imp_LeadsTo: "[| A <= B; F ∈ program |] ==> F ∈ A LeadsTo B"
    apply (simp (no_asm_simp) add: LeadsTo_def)
    apply (blast intro: subset_imp_leadsTo)
    done

    lemma empty_LeadsTo: "F:0 LeadsTo A <-> F ∈ program"
    by (auto dest: LeadsTo_type [THEN subsetD]
                intro: empty_subsetI [THEN subset_imp_LeadsTo])
    declare empty_LeadsTo [iff]

    lemma LeadsTo_state: "F ∈ A LeadsTo state <-> F ∈ program"
    by (auto dest: LeadsTo_type [THEN subsetD] simp add: LeadsTo_eq)
    declare LeadsTo_state [iff]

    lemma LeadsTo_weaken_R: "[| F ∈ A LeadsTo A';  A'<=B'|] ==> F ∈ A LeadsTo B'"
    apply (unfold LeadsTo_def)
    apply (auto intro: leadsTo_weaken_R)
    done

    lemma LeadsTo_weaken_L: "[| F ∈ A LeadsTo A'; B <= A |] ==> F ∈ B LeadsTo A'"
    apply (unfold LeadsTo_def)
    apply (auto intro: leadsTo_weaken_L)
    done

    lemma LeadsTo_weaken: "[| F ∈ A LeadsTo A'; B<=A; A'<=B' |] ==> F ∈ B LeadsTo B'"
    by (blast intro: LeadsTo_weaken_R LeadsTo_weaken_L LeadsTo_Trans)

    lemma Always_LeadsTo_weaken:
    "[| F ∈ Always(C);  F ∈ A LeadsTo A'; C Int B <= A;   C Int A' <= B' |]
          ==> F ∈ B LeadsTo B'"
    apply (blast dest: Always_LeadsToI intro: LeadsTo_weaken Always_LeadsToD)
    done

    (** Two theorems for "proof lattices" **)

    lemma LeadsTo_Un_post: "F ∈ A LeadsTo B ==> F:(A Un B) LeadsTo B"
    by (blast dest: LeadsTo_type [THEN subsetD]
                 intro: LeadsTo_Un subset_imp_LeadsTo)

    lemma LeadsTo_Trans_Un: "[| F ∈ A LeadsTo B;  F ∈ B LeadsTo C |]
          ==> F ∈ (A Un B) LeadsTo C"
    apply (blast intro: LeadsTo_Un subset_imp_LeadsTo LeadsTo_weaken_L LeadsTo_Trans dest: LeadsTo_type [THEN subsetD])
    done

    (** Distributive laws **)
    lemma LeadsTo_Un_distrib: "(F ∈ (A Un B) LeadsTo C)  <-> (F ∈ A LeadsTo C & F ∈ B LeadsTo C)"
    by (blast intro: LeadsTo_Un LeadsTo_weaken_L)

    lemma LeadsTo_UN_distrib: "(F ∈ (\<Union>i ∈ I. A(i)) LeadsTo B) <->  (∀i ∈ I. F ∈ A(i) LeadsTo B) & F ∈ program"
    by (blast dest: LeadsTo_type [THEN subsetD]
                 intro: LeadsTo_UN LeadsTo_weaken_L)

    lemma LeadsTo_Union_distrib: "(F ∈ Union(S) LeadsTo B)  <->  (∀A ∈ S. F ∈ A LeadsTo B) & F ∈ program"
    by (blast dest: LeadsTo_type [THEN subsetD]
                 intro: LeadsTo_Union LeadsTo_weaken_L)

    (** More rules using the premise "Always(I)" **)

    lemma EnsuresI: "[| F:(A-B) Co (A Un B);  F ∈ transient (A-B) |] ==> F ∈ A Ensures B"
    apply (simp add: Ensures_def Constrains_eq_constrains)
    apply (blast intro: ensuresI constrains_weaken transient_strengthen dest: constrainsD2)
    done

    lemma Always_LeadsTo_Basis: "[| F ∈ Always(I); F ∈ (I Int (A-A')) Co (A Un A');
             F ∈ transient (I Int (A-A')) |]
      ==> F ∈ A LeadsTo A'"
    apply (rule Always_LeadsToI, assumption)
    apply (blast intro: EnsuresI LeadsTo_Basis Always_ConstrainsD [THEN Constrains_weaken] transient_strengthen)
    done

    (*Set difference: maybe combine with leadsTo_weaken_L??
      This is the most useful form of the "disjunction" rule*)
    lemma LeadsTo_Diff:
         "[| F ∈ (A-B) LeadsTo C;  F ∈ (A Int B) LeadsTo C |] ==> F ∈ A LeadsTo C"
    by (blast intro: LeadsTo_Un LeadsTo_weaken)

    lemma LeadsTo_UN_UN:
         "[|(!!i. i ∈ I ==> F ∈ A(i) LeadsTo A'(i)); F ∈ program |]
          ==> F ∈ (\<Union>i ∈ I. A(i)) LeadsTo (\<Union>i ∈ I. A'(i))"
    apply (rule LeadsTo_Union, auto)
    apply (blast intro: LeadsTo_weaken_R)
    done

    (*Binary union version*)
    lemma LeadsTo_Un_Un:
      "[| F ∈ A LeadsTo A'; F ∈ B LeadsTo B' |] ==> F:(A Un B) LeadsTo (A' Un B')"
    by (blast intro: LeadsTo_Un LeadsTo_weaken_R)

    (** The cancellation law **)

    lemma LeadsTo_cancel2: "[| F ∈ A LeadsTo(A' Un B); F ∈ B LeadsTo B' |] ==> F ∈ A LeadsTo (A' Un B')"
    by (blast intro: LeadsTo_Un_Un subset_imp_LeadsTo LeadsTo_Trans dest: LeadsTo_type [THEN subsetD])

    lemma Un_Diff: "A Un (B - A) = A Un B"
    by auto

    lemma LeadsTo_cancel_Diff2: "[| F ∈ A LeadsTo (A' Un B); F ∈ (B-A') LeadsTo B' |] ==> F ∈ A LeadsTo (A' Un B')"
    apply (rule LeadsTo_cancel2)
    prefer 2 apply assumption
    apply (simp (no_asm_simp) add: Un_Diff)
    done

    lemma LeadsTo_cancel1: "[| F ∈ A LeadsTo (B Un A'); F ∈ B LeadsTo B' |] ==> F ∈ A LeadsTo (B' Un A')"
    apply (simp add: Un_commute)
    apply (blast intro!: LeadsTo_cancel2)
    done

    lemma Diff_Un2: "(B - A) Un A = B Un A"
    by auto

    lemma LeadsTo_cancel_Diff1: "[| F ∈ A LeadsTo (B Un A'); F ∈ (B-A') LeadsTo B' |] ==> F ∈ A LeadsTo (B' Un A')"
    apply (rule LeadsTo_cancel1)
    prefer 2 apply assumption
    apply (simp (no_asm_simp) add: Diff_Un2)
    done

    (** The impossibility law **)

    (*The set "A" may be non-empty, but it contains no reachable states*)
    lemma LeadsTo_empty: "F ∈ A LeadsTo 0 ==> F ∈ Always (state -A)"
    apply (simp (no_asm_use) add: LeadsTo_def Always_eq_includes_reachable)
    apply (cut_tac reachable_type)
    apply (auto dest!: leadsTo_empty)
    done

    (** PSP ∈ Progress-Safety-Progress **)

    (*Special case of PSP ∈ Misra's "stable conjunction"*)
    lemma PSP_Stable: "[| F ∈ A LeadsTo A';  F ∈ Stable(B) |]==> F:(A Int B) LeadsTo (A' Int B)"
    apply (simp add: LeadsTo_def Stable_eq_stable, clarify)
    apply (drule psp_stable, assumption)
    apply (simp add: Int_ac)
    done

    lemma PSP_Stable2: "[| F ∈ A LeadsTo A'; F ∈ Stable(B) |] ==> F ∈ (B Int A) LeadsTo (B Int A')"
    apply (simp (no_asm_simp) add: PSP_Stable Int_ac)
    done

    lemma PSP: "[| F ∈ A LeadsTo A'; F ∈ B Co B'|]==> F ∈ (A Int B') LeadsTo ((A' Int B) Un (B' - B))"
    apply (simp (no_asm_use) add: LeadsTo_def Constrains_eq_constrains)
    apply (blast dest: psp intro: leadsTo_weaken)
    done

    lemma PSP2: "[| F ∈ A LeadsTo A'; F ∈ B Co B' |]==> F:(B' Int A) LeadsTo ((B Int A') Un (B' - B))"
    by (simp (no_asm_simp) add: PSP Int_ac)

    lemma PSP_Unless:
    "[| F ∈ A LeadsTo A'; F ∈ B Unless B'|]==> F:(A Int B) LeadsTo ((A' Int B) Un B')"
    apply (unfold Unless_def)
    apply (drule PSP, assumption)
    apply (blast intro: LeadsTo_Diff LeadsTo_weaken subset_imp_LeadsTo)
    done

    (*** Induction rules ***)

    (** Meta or object quantifier ????? **)
    lemma LeadsTo_wf_induct: "[| wf(r);
             ∀m ∈ I. F ∈ (A Int f-``{m}) LeadsTo
                                ((A Int f-``(converse(r) `` {m})) Un B);
             field(r)<=I; A<=f-``I; F ∈ program |]
          ==> F ∈ A LeadsTo B"
    apply (simp (no_asm_use) add: LeadsTo_def)
    apply auto
    apply (erule_tac I = I and f = f in leadsTo_wf_induct, safe)
    apply (drule_tac [2] x = m in bspec, safe)
    apply (rule_tac [2] A' = "reachable (F) Int (A Int f -`` (converse (r) ``{m}) Un B) " in leadsTo_weaken_R)
    apply (auto simp add: Int_assoc)
    done

    lemma LessThan_induct: "[| ∀m ∈ nat. F:(A Int f-``{m}) LeadsTo ((A Int f-``m) Un B);
          A<=f-``nat; F ∈ program |] ==> F ∈ A LeadsTo B"
    apply (rule_tac A1 = nat and f1 = "%x. x" in wf_measure [THEN LeadsTo_wf_induct])
    apply (simp_all add: nat_measure_field)
    apply (simp add: ltI Image_inverse_lessThan vimage_def [symmetric])
    done

    (******
     To be ported ??? I am not sure.

      integ_0_le_induct
      LessThan_bounded_induct
      GreaterThan_bounded_induct

    *****)

    (*** Completion ∈ Binary and General Finite versions ***)

    lemma Completion: "[| F ∈ A LeadsTo (A' Un C);  F ∈ A' Co (A' Un C);
             F ∈ B LeadsTo (B' Un C);  F ∈ B' Co (B' Un C) |]
          ==> F ∈ (A Int B) LeadsTo ((A' Int B') Un C)"
    apply (simp (no_asm_use) add: LeadsTo_def Constrains_eq_constrains Int_Un_distrib)
    apply (blast intro: completion leadsTo_weaken)
    done

    lemma Finite_completion_aux:
         "[| I ∈ Fin(X);F ∈ program |]
          ==> (∀i ∈ I. F ∈ (A(i)) LeadsTo (A'(i) Un C)) -->
              (∀i ∈ I. F ∈ (A'(i)) Co (A'(i) Un C)) -->
              F ∈ (\<Inter>i ∈ I. A(i)) LeadsTo ((\<Inter>i ∈ I. A'(i)) Un C)"
    apply (erule Fin_induct)
    apply (auto simp del: INT_simps simp add: Inter_0)
    apply (rule Completion, auto)
    apply (simp del: INT_simps add: INT_extend_simps)
    apply (blast intro: Constrains_INT)
    done

    lemma Finite_completion:
         "[| I ∈ Fin(X); !!i. i ∈ I ==> F ∈ A(i) LeadsTo (A'(i) Un C);
             !!i. i ∈ I ==> F ∈ A'(i) Co (A'(i) Un C);
             F ∈ program |]
          ==> F ∈ (\<Inter>i ∈ I. A(i)) LeadsTo ((\<Inter>i ∈ I. A'(i)) Un C)"
    by (blast intro: Finite_completion_aux [THEN mp, THEN mp])

    lemma Stable_completion:
         "[| F ∈ A LeadsTo A';  F ∈ Stable(A');
             F ∈ B LeadsTo B';  F ∈ Stable(B') |]
        ==> F ∈ (A Int B) LeadsTo (A' Int B')"
    apply (unfold Stable_def)
    apply (rule_tac C1 = 0 in Completion [THEN LeadsTo_weaken_R])
        prefer 5
        apply blast
    apply auto
    done

    lemma Finite_stable_completion:
         "[| I ∈ Fin(X);
             (!!i. i ∈ I ==> F ∈ A(i) LeadsTo A'(i));
             (!!i. i ∈ I ==>F ∈ Stable(A'(i)));   F ∈ program  |]
          ==> F ∈ (\<Inter>i ∈ I. A(i)) LeadsTo (\<Inter>i ∈ I. A'(i))"
    apply (unfold Stable_def)
    apply (rule_tac C1 = 0 in Finite_completion [THEN LeadsTo_weaken_R], simp_all)
    apply (rule_tac [3] subset_refl, auto)
    done

    ML
    {*
    val LeadsTo_eq = thm "LeadsTo_eq";
    val LeadsTo_type = thm "LeadsTo_type";
    val Always_LeadsTo_pre = thm "Always_LeadsTo_pre";
    val Always_LeadsTo_post = thm "Always_LeadsTo_post";
    val Always_LeadsToI = thm "Always_LeadsToI";
    val Always_LeadsToD = thm "Always_LeadsToD";
    val LeadsTo_Basis = thm "LeadsTo_Basis";
    val LeadsTo_Trans = thm "LeadsTo_Trans";
    val LeadsTo_Union = thm "LeadsTo_Union";
    val leadsTo_imp_LeadsTo = thm "leadsTo_imp_LeadsTo";
    val LeadsTo_Un_duplicate = thm "LeadsTo_Un_duplicate";
    val LeadsTo_Un_duplicate2 = thm "LeadsTo_Un_duplicate2";
    val LeadsTo_UN = thm "LeadsTo_UN";
    val LeadsTo_Un = thm "LeadsTo_Un";
    val single_LeadsTo_I = thm "single_LeadsTo_I";
    val subset_imp_LeadsTo = thm "subset_imp_LeadsTo";
    val empty_LeadsTo = thm "empty_LeadsTo";
    val LeadsTo_state = thm "LeadsTo_state";
    val LeadsTo_weaken_R = thm "LeadsTo_weaken_R";
    val LeadsTo_weaken_L = thm "LeadsTo_weaken_L";
    val LeadsTo_weaken = thm "LeadsTo_weaken";
    val Always_LeadsTo_weaken = thm "Always_LeadsTo_weaken";
    val LeadsTo_Un_post = thm "LeadsTo_Un_post";
    val LeadsTo_Trans_Un = thm "LeadsTo_Trans_Un";
    val LeadsTo_Un_distrib = thm "LeadsTo_Un_distrib";
    val LeadsTo_UN_distrib = thm "LeadsTo_UN_distrib";
    val LeadsTo_Union_distrib = thm "LeadsTo_Union_distrib";
    val EnsuresI = thm "EnsuresI";
    val Always_LeadsTo_Basis = thm "Always_LeadsTo_Basis";
    val LeadsTo_Diff = thm "LeadsTo_Diff";
    val LeadsTo_UN_UN = thm "LeadsTo_UN_UN";
    val LeadsTo_Un_Un = thm "LeadsTo_Un_Un";
    val LeadsTo_cancel2 = thm "LeadsTo_cancel2";
    val Un_Diff = thm "Un_Diff";
    val LeadsTo_cancel_Diff2 = thm "LeadsTo_cancel_Diff2";
    val LeadsTo_cancel1 = thm "LeadsTo_cancel1";
    val Diff_Un2 = thm "Diff_Un2";
    val LeadsTo_cancel_Diff1 = thm "LeadsTo_cancel_Diff1";
    val LeadsTo_empty = thm "LeadsTo_empty";
    val PSP_Stable = thm "PSP_Stable";
    val PSP_Stable2 = thm "PSP_Stable2";
    val PSP = thm "PSP";
    val PSP2 = thm "PSP2";
    val PSP_Unless = thm "PSP_Unless";
    val LeadsTo_wf_induct = thm "LeadsTo_wf_induct";
    val LessThan_induct = thm "LessThan_induct";
    val Completion = thm "Completion";
    val Finite_completion = thm "Finite_completion";
    val Stable_completion = thm "Stable_completion";
    val Finite_stable_completion = thm "Finite_stable_completion";

    (*proves "ensures/leadsTo" properties when the program is specified*)
    fun gen_ensures_tac(cs,ss) sact =
        SELECT_GOAL
          (EVERY [REPEAT (Always_Int_tac 1),
                  etac Always_LeadsTo_Basis 1
                      ORELSE   (*subgoal may involve LeadsTo, leadsTo or ensures*)
                      REPEAT (ares_tac [LeadsTo_Basis, leadsTo_Basis,
                                        EnsuresI, ensuresI] 1),
                  (*now there are two subgoals: co & transient*)
                  simp_tac (ss addsimps !program_defs_ref) 2,
                  res_inst_tac [("act", sact)] transientI 2,
                     (*simplify the command's domain*)
                  simp_tac (ss addsimps [domain_def]) 3,
                  (* proving the domain part *)
                 clarify_tac cs 3, dtac swap 3, force_tac (cs,ss) 4,
                 rtac ReplaceI 3, force_tac (cs,ss) 3, force_tac (cs,ss) 4,
                 asm_full_simp_tac ss 3, rtac conjI 3, simp_tac ss 4,
                 REPEAT (rtac state_update_type 3),
                 gen_constrains_tac (cs,ss) 1,
                 ALLGOALS (clarify_tac cs),
                 ALLGOALS (asm_full_simp_tac (ss addsimps [st_set_def])),
                            ALLGOALS (clarify_tac cs),
                ALLGOALS (asm_lr_simp_tac ss)]);

    fun ensures_tac sact = gen_ensures_tac (claset(), simpset()) sact;
    *}

    method_setup ensures_tac = {*
        fn args => fn ctxt =>
            Method.goal_args' (Scan.lift Args.name)
               (gen_ensures_tac (local_clasimpset_of ctxt))
               args ctxt *}
        "for proving progress properties"

    end

lemma LeadsTo_eq:

      st_set(B) ==> A LeadsTo B = {F ∈ program . F ∈ reachable(F) ∩ A leadsTo B}

lemma LeadsTo_type:

      A LeadsTo B ⊆ program

lemma Always_LeadsTo_pre:

      F ∈ Always(I) ==> F ∈ I ∩ A LeadsTo A' <-> F ∈ A LeadsTo A'

lemma Always_LeadsTo_post:

      F ∈ Always(I) ==> F ∈ A LeadsTo I ∩ A' <-> F ∈ A LeadsTo A'

lemma Always_LeadsToI:

      [| F ∈ Always(C); F ∈ C ∩ A LeadsTo A' |] ==> F ∈ A LeadsTo A'

lemma Always_LeadsToD:

      [| F ∈ Always(C); F ∈ A LeadsTo A' |] ==> F ∈ A LeadsTo C ∩ A'

lemma LeadsTo_Basis:

      F ∈ A Ensures B ==> F ∈ A LeadsTo B

lemma LeadsTo_Trans:

      [| F ∈ A LeadsTo B; F ∈ B LeadsTo C |] ==> F ∈ A LeadsTo C

lemma LeadsTo_Union:

      [| !!A. A ∈ S ==> F ∈ A LeadsTo B; F ∈ program |] ==> F ∈ \<Union>S LeadsTo B

lemma leadsTo_imp_LeadsTo:

      F ∈ A leadsTo B ==> F ∈ A LeadsTo B

lemma LeadsTo_Un_duplicate:

      F ∈ A LeadsTo A' ∪ A' ==> F ∈ A LeadsTo A'

lemma LeadsTo_Un_duplicate2:

      F ∈ A LeadsTo A' ∪ C ∪ C ==> F ∈ A LeadsTo A' ∪ C

lemma LeadsTo_UN:

      [| !!i. i ∈ I ==> F ∈ A(i) LeadsTo B; F ∈ program |]
      ==> F ∈ (\<Union>i∈I. A(i)) LeadsTo B

lemma LeadsTo_Un:

      [| F ∈ A LeadsTo C; F ∈ B LeadsTo C |] ==> F ∈ A ∪ B LeadsTo C

lemma single_LeadsTo_I:

      [| !!s. s ∈ A ==> F ∈ {s} LeadsTo B; F ∈ program |] ==> F ∈ A LeadsTo B

lemma subset_imp_LeadsTo:

      [| A ⊆ B; F ∈ program |] ==> F ∈ A LeadsTo B

lemma empty_LeadsTo:

      F ∈ 0 LeadsTo A <-> F ∈ program

lemma LeadsTo_state:

      F ∈ A LeadsTo state <-> F ∈ program

lemma LeadsTo_weaken_R:

      [| F ∈ A LeadsTo A'; A' ⊆ B' |] ==> F ∈ A LeadsTo B'

lemma LeadsTo_weaken_L:

      [| F ∈ A LeadsTo A'; B ⊆ A |] ==> F ∈ B LeadsTo A'

lemma LeadsTo_weaken:

      [| F ∈ A LeadsTo A'; B ⊆ A; A' ⊆ B' |] ==> F ∈ B LeadsTo B'

lemma Always_LeadsTo_weaken:

      [| F ∈ Always(C); F ∈ A LeadsTo A'; C ∩ B ⊆ A; C ∩ A' ⊆ B' |]
      ==> F ∈ B LeadsTo B'

lemma LeadsTo_Un_post:

      F ∈ A LeadsTo B ==> F ∈ A ∪ B LeadsTo B

lemma LeadsTo_Trans_Un:

      [| F ∈ A LeadsTo B; F ∈ B LeadsTo C |] ==> F ∈ A ∪ B LeadsTo C

lemma LeadsTo_Un_distrib:

      F ∈ A ∪ B LeadsTo C <-> F ∈ A LeadsTo C ∧ F ∈ B LeadsTo C

lemma LeadsTo_UN_distrib:

      F ∈ (\<Union>i∈I. A(i)) LeadsTo B <-> (∀i∈I. F ∈ A(i) LeadsTo B) ∧ F ∈ program

lemma LeadsTo_Union_distrib:

      F ∈ \<Union>S LeadsTo B <-> (∀A∈S. F ∈ A LeadsTo B) ∧ F ∈ program

lemma EnsuresI:

      [| F ∈ A - B Co A ∪ B; F ∈ transient(A - B) |] ==> F ∈ A Ensures B

lemma Always_LeadsTo_Basis:

      [| F ∈ Always(I); F ∈ I ∩ (A - A') Co A ∪ A'; F ∈ transient(I ∩ (A - A')) |]
      ==> F ∈ A LeadsTo A'

lemma LeadsTo_Diff:

      [| F ∈ A - B LeadsTo C; F ∈ A ∩ B LeadsTo C |] ==> F ∈ A LeadsTo C

lemma LeadsTo_UN_UN:

      [| !!i. i ∈ I ==> F ∈ A(i) LeadsTo A'(i); F ∈ program |]
      ==> F ∈ (\<Union>i∈I. A(i)) LeadsTo (\<Union>i∈I. A'(i))

lemma LeadsTo_Un_Un:

      [| F ∈ A LeadsTo A'; F ∈ B LeadsTo B' |] ==> F ∈ A ∪ B LeadsTo A' ∪ B'

lemma LeadsTo_cancel2:

      [| F ∈ A LeadsTo A' ∪ B; F ∈ B LeadsTo B' |] ==> F ∈ A LeadsTo A' ∪ B'

lemma Un_Diff:

      A ∪ (B - A) = A ∪ B

lemma LeadsTo_cancel_Diff2:

      [| F ∈ A LeadsTo A' ∪ B; F ∈ B - A' LeadsTo B' |] ==> F ∈ A LeadsTo A' ∪ B'

lemma LeadsTo_cancel1:

      [| F ∈ A LeadsTo B ∪ A'; F ∈ B LeadsTo B' |] ==> F ∈ A LeadsTo B' ∪ A'

lemma Diff_Un2:

      B - A ∪ A = B ∪ A

lemma LeadsTo_cancel_Diff1:

      [| F ∈ A LeadsTo B ∪ A'; F ∈ B - A' LeadsTo B' |] ==> F ∈ A LeadsTo B' ∪ A'

lemma LeadsTo_empty:

      F ∈ A LeadsTo 0 ==> F ∈ Always(state - A)

lemma PSP_Stable:

      [| F ∈ A LeadsTo A'; F ∈ Stable(B) |] ==> F ∈ A ∩ B LeadsTo A' ∩ B

lemma PSP_Stable2:

      [| F ∈ A LeadsTo A'; F ∈ Stable(B) |] ==> F ∈ B ∩ A LeadsTo B ∩ A'

lemma PSP:

      [| F ∈ A LeadsTo A'; F ∈ B Co B' |] ==> F ∈ A ∩ B' LeadsTo A' ∩ B ∪ (B' - B)

lemma PSP2:

      [| F ∈ A LeadsTo A'; F ∈ B Co B' |] ==> F ∈ B' ∩ A LeadsTo B ∩ A' ∪ (B' - B)

lemma PSP_Unless:

      [| F ∈ A LeadsTo A'; F ∈ B Unless B' |] ==> F ∈ A ∩ B LeadsTo A' ∩ B ∪ B'

lemma LeadsTo_wf_induct:

      [| wf(r); ∀m∈I. F ∈ A ∩ f -`` {m} LeadsTo A ∩ f -`` (converse(r) `` {m}) ∪ B;
         field(r) ⊆ I; A ⊆ f -`` I; F ∈ program |]
      ==> F ∈ A LeadsTo B

lemma LessThan_induct:

      [| ∀m∈nat. F ∈ A ∩ f -`` {m} LeadsTo A ∩ f -`` m ∪ B; A ⊆ f -`` nat;
         F ∈ program |]
      ==> F ∈ A LeadsTo B

lemma Completion:

      [| F ∈ A LeadsTo A' ∪ C; F ∈ A' Co A' ∪ C; F ∈ B LeadsTo B' ∪ C;
         F ∈ B' Co B' ∪ C |]
      ==> F ∈ A ∩ B LeadsTo A' ∩ B' ∪ C

lemma Finite_completion_aux:

      [| I ∈ Fin(X); F ∈ program |]
      ==> (∀i∈I. F ∈ A(i) LeadsTo A'(i) ∪ C) -->
          (∀i∈I. F ∈ A'(i) Co A'(i) ∪ C) -->
          F ∈ (\<Inter>i∈I. A(i)) LeadsTo (\<Inter>i∈I. A'(i)) ∪ C

lemma Finite_completion:

      [| I ∈ Fin(X); !!i. i ∈ I ==> F ∈ A(i) LeadsTo A'(i) ∪ C;
         !!i. i ∈ I ==> F ∈ A'(i) Co A'(i) ∪ C; F ∈ program |]
      ==> F ∈ (\<Inter>i∈I. A(i)) LeadsTo (\<Inter>i∈I. A'(i)) ∪ C

lemma Stable_completion:

      [| F ∈ A LeadsTo A'; F ∈ Stable(A'); F ∈ B LeadsTo B'; F ∈ Stable(B') |]
      ==> F ∈ A ∩ B LeadsTo A' ∩ B'

lemma Finite_stable_completion:

      [| I ∈ Fin(X); !!i. i ∈ I ==> F ∈ A(i) LeadsTo A'(i);
         !!i. i ∈ I ==> F ∈ Stable(A'(i)); F ∈ program |]
      ==> F ∈ (\<Inter>i∈I. A(i)) LeadsTo (\<Inter>i∈I. A'(i))