Theory Language_Composition

(*
Title: Strong-Security
Authors: Sylvia Grewe, Alexander Lux, Heiko Mantel, Jens Sauer
*)
theory Language_Composition
imports Strongly_Secure_Skip_Assign
begin

context Strongly_Secure_Programs
begin        
  
theorem Compositionality_Seq: 
  assumes relatedpart1: "[c1] ≈⇘d[c1']"
  assumes relatedpart2: "[c2] ≈⇘d[c2']"
  shows "[c1;c2] ≈⇘d[c1';c2']"
proof -
  define R0 where "R0 = {(S1,S2). c1 c1' c2 c2' W W'. 
    S1 = (c1;c2)#W  S2 = (c1';c2')#W'  
    [c1] ≈⇘d[c1']  [c2] ≈⇘d[c2']  W ≈⇘dW'}"
  
  from relatedpart1 relatedpart2 trivialpair_in_USdB
  have inR0: "([c1;c2],[c1';c2'])  R0"
    by (simp add: R0_def)
   
  have uptoR0: "d_Bisimulation_Up_To_USdB d R0"
    proof (simp add: d_Bisimulation_Up_To_USdB_def, auto)
        from USdBsym 
        show "sym R0"
          by (simp add: sym_def R0_def, fastforce)
      next 
        fix S1 S2
        assume inR0: "(S1,S2)  R0"
        with USdBeqlen show "length S1 = length S2"
          by (auto simp add: R0_def)
      next
        fix S1 S2 RS m1 m2 m1' i
        assume inR0: "(S1,S2)  R0"
        assume irange: "i < length S1"
        assume S1step: "S1!i,m1  RS,m2"
        assume dequal: "m1 =⇘dm1'"
        from inR0 obtain c1 c1' c2 c2' V V'
          where R0def': "S1 = (c1;c2)#V  S2 = (c1';c2')#V'  
          [c1] ≈⇘d[c1']  [c2] ≈⇘d[c2']  V ≈⇘dV'"
          by (simp add: R0_def, force)

        with irange have case_distinction1: 
          "i = 0  (V  []  i  0)"
          by auto
        moreover
        have case1: "i = 0  
          RS' m2'. S2!i,m1'  RS',m2' 
             ((RS,RS')  R0  RS ≈⇘dRS')  m2 =⇘dm2'"
          proof -
            assume i0: "i = 0"

              ― ‹get the two different sub-cases:›
            with R0def' S1step obtain c3 W where case_distinction: 
              "RS = [c2]  c1,m1  [],m2
               RS = (c3;c2)#W  c1,m1  c3#W,m2"
              by (simp, metis MWLfSteps_det_cases(3))
            moreover
              ― ‹Case 1: first command terminates›
            {
              assume RSassump: "RS = [c2]"
              assume StepAssump: "c1,m1  [],m2" 

              from USdBeqlen[of "[]"] StepAssump R0def' 
                USdB_Strong_d_Bisimulation dequal
                strongdB_aux[of "d" "≈⇘d⇙" "i"
                "[c1]" "[c1']" "m1" "[]" "m2" "m1'"] i0
              obtain W' m2' where c1c1'reason: 
                "c1',m1'  W',m2'  W' = [] 
                 [] ≈⇘dW'  m2 =⇘dm2'"
                by fastforce

              with c1c1'reason have conclpart:
                "c1';c2',m1'  [c2'],m2'  m2 =⇘dm2'"
                by (simp add: MWLfSteps_det.seq1)
          
              with RSassump R0def' i0 have case1_concl:
                "RS' m2'. S2!i,m1'  RS',m2' 
                 ((RS,RS')  R0  RS ≈⇘dRS')  m2 =⇘dm2'"   
                by (simp, rule_tac x="[c2']" in exI, auto)      
            }
            moreover
              ― ‹Case 2: first command does not terminate›
            {
              assume RSassump: "RS = (c3;c2)#W"
              assume StepAssump: "c1,m1  c3#W,m2"
              
              from StepAssump R0def' USdB_Strong_d_Bisimulation dequal
                strongdB_aux[of "d" "≈⇘d⇙" "i" "[c1]" "[c1']" "m1" 
                "c3#W" "m2" "m1'"] i0 
              obtain V'' m2' where c1c1'reason: 
                "c1',m1'  V'',m2' 
                 (c3#W) ≈⇘dV''  m2 =⇘dm2'"
                by fastforce
 
              with USdBeqlen[of "c3#W" "V''"] obtain c3' W' 
                where V''reason:
                "V'' = c3'#W'  length W = length W'"
                by (cases V'', force, force)
          
              with c1c1'reason have conclpart1:
                "c1';c2',m1'  (c3';c2')#W',m2'  m2 =⇘dm2'"
                by (simp add: MWLfSteps_det.seq2)

              from V''reason c1c1'reason 
                USdB_decomp_head_tail[of "c3" "W"] 
                USdB_Strong_d_Bisimulation
              have c3aWinUSDB: 
                "[c3] ≈⇘d[c3']  W ≈⇘dW'"
                by blast
        
              with R0def' have conclpart2:
                "((c3;c2)#W,(c3';c2')#W')  R0"
                by (auto simp add: R0_def)

              with i0 RSassump R0def' V''reason conclpart1 
              have case2_concl:
                "RS' m2'. S2!i,m1'  RS',m2' 
                ((RS,RS')  R0  RS ≈⇘dRS')  m2 =⇘dm2'"
                by (rule_tac x="(c3';c2')#W'" in exI, auto)
            } 
            ultimately
            show "RS' m2'. S2!i,m1'  RS',m2' 
               ((RS,RS')  R0  RS ≈⇘dRS')  m2 =⇘dm2'"
              by blast
          qed
          moreover
          have case2: " V  []; i  0 
             RS' m2'. S2!i,m1'  RS',m2' 
               ((RS,RS')  R0  RS ≈⇘dRS')  m2 =⇘dm2'"
            proof - 
              assume Vnonempt: "V  []"
              assume inot0: "i  0"

              with Vnonempt irange R0def' have i1range:
                "(i-Suc 0) < length V"
                by simp

              from inot0 R0def' have S1ieq: "S1!i = V!(i-Suc 0)"
                by auto

              from inot0 R0def' have "S2!i = V'!(i-Suc 0)"
                by auto
              
              with S1ieq R0def' S1step i1range dequal 
                USdB_Strong_d_Bisimulation
                strongdB_aux[of "d" "USdB d"
                "i-Suc 0" "V" "V'" "m1" "RS" "m2" "m1'"]
              show "RS' m2'. S2!i,m1'  RS',m2' 
                ((RS,RS')  R0  RS ≈⇘dRS')  m2 =⇘dm2'"
                by force
            qed
          ultimately show "RS' m2'. S2!i,m1'  RS',m2' 
           ((RS,RS')  R0  RS ≈⇘dRS')  m2 =⇘dm2'"
            by auto
        qed          
  
  hence "R0  ≈⇘d⇙"
    by (rule Up_To_Technique)
  
  with inR0 show ?thesis
    by auto
  
qed

theorem Compositionality_Fork:
  fixes V::"('exp,'id) MWLfCom list"
  assumes relatedmain: "[c] ≈⇘d[c']"
  assumes relatedthreads: "V ≈⇘dV'"
  shows "[fork c V] ≈⇘d[fork c' V']"  
proof -
  define R0 where "R0 = {(F1,F2). c1 c1' W W'. 
    F1 = [fork c1 W]  F2 = [fork c1' W']
     [c1] ≈⇘d[c1']  W ≈⇘dW'}"
  from relatedmain relatedthreads 
  have inR0: "([fork c V],[fork c' V'])  R0"
    by (simp add: R0_def)
  
  have uptoR0: "d_Bisimulation_Up_To_USdB d R0"
    proof (simp add: d_Bisimulation_Up_To_USdB_def, auto)
      from USdBsym show "sym R0"
        by (simp add: R0_def sym_def, auto)
    next 
      fix F1 F2
      assume inR0: "(F1,F2)  R0"
      with R0_def USdBeqlen show "length F1 = length F2"
        by auto
    next
      fix F1 F2 c1V m1 m2 m1' i
      assume inR0: "(F1,F2)  R0"
      assume irange: "i < length F1"
      assume F1step: "F1!i,m1  c1V,m2"
      assume dequal: "m1 =⇘dm1'"

      from inR0 obtain c1 c1' V V' 
        where R0def': "F1 = [fork c1 V]  F2 = [fork c1' V']  
        [c1] ≈⇘d[c1']  V ≈⇘dV'"
        by (simp add: R0_def, force)

      from irange R0def' F1step
      have rew: "c1V = c1#V  m2 = m1"
        by (simp, metis MWLf_semantics.MWLfSteps_det_cases(6))

      from irange R0def' MWLfSteps_det.fork have F2step: 
        "F2!i,m1'  c1'#V',m1'"
        by force
      
      from R0def' USdB_comp_head_tail have conclpart: 
         "((c1#V,c1'#V')  R0  (c1#V) ≈⇘d(c1'#V'))"
        by auto
        
      with irange rew inR0 F1step dequal R0def' F2step
      show "c1V' m2'. F2!i,m1'  c1V',m2'  
        ((c1V,c1V')  R0  c1V ≈⇘dc1V')  m2 =⇘dm2'"
        by fastforce
    qed
     
  hence "R0  ≈⇘d⇙"
    by (rule Up_To_Technique)
  
  with inR0 show ?thesis
    by auto
  
qed

theorem Compositionality_If:
  assumes dind_or_branchesrelated: 
  "b ≡⇘db'  [c1] ≈⇘d[c2]  [c1'] ≈⇘d[c2']"
  assumes branch1related: "[c1] ≈⇘d[c1']"
  assumes branch2related: "[c2] ≈⇘d[c2']"
  shows "[if b then c1 else c2 fi] ≈⇘d[if b' then c1' else c2' fi]"
proof -
  define R1 where "R1 = {(I1,I2). c1 c1' c2 c2' b b'.
    I1 = [if b then c1 else c2 fi]  I2 = [if b' then c1' else c2' fi] 
    [c1] ≈⇘d[c1']  [c2] ≈⇘d[c2']  b ≡⇘db'}"

  define R2 where "R2 = {(I1,I2). c1 c1' c2 c2' b b'.
    I1 = [if b then c1 else c2 fi]  I2 = [if b' then c1' else c2' fi] 
    [c1] ≈⇘d[c1']  [c2] ≈⇘d[c2'] 
    ([c1] ≈⇘d[c2]  [c1'] ≈⇘d[c2'])}"

  define R0 where "R0 = R1  R2"

  from dind_or_branchesrelated branch1related branch2related
  have inR0: "([if b then c1 else c2 fi],[if b' then c1' else c2' fi])  R0"
    by (simp add: R0_def R1_def R2_def)

  have uptoR0: "d_Bisimulation_Up_To_USdB d R0"
    proof (simp add: d_Bisimulation_Up_To_USdB_def, auto)
        from USdBsym d_indistinguishable_sym
        have symR1: "sym R1"
          by (simp add: sym_def R1_def, fastforce)
        from USdBsym 
        have symR2: "sym R2"
          by (simp add: sym_def R2_def, fastforce)
        
        from symR1 symR2 show "sym R0"
          by (simp add: sym_def R0_def)
      next
        fix I1 I2
        assume inR0: "(I1,I2)  R0"
        thus "length I1 = length I2"
          by (simp add: R0_def R1_def R2_def, auto)
      next 
        fix I1 I2 RS m1 m1' m2 i
        assume inR0: "(I1,I2)  R0"
        assume irange: "i < length I1"
        assume I1step: "I1!i,m1  RS,m2"
        assume dequal: "m1 =⇘dm1'"

        have inR1case: "(I1,I2)  R1
           RS' m2'. I2!i,m1'  RS',m2' 
             ((RS,RS')  R0  RS ≈⇘dRS')  m2 =⇘dm2'"
          proof -
            assume inR1: "(I1,I2)  R1"
            
            then obtain c1 c1' c2 c2' b b' where R1def':
              "I1 = [if b then c1 else c2 fi] 
               I2 = [if b' then c1' else c2' fi] 
              [c1] ≈⇘d[c1']  [c2] ≈⇘d[c2']  b ≡⇘db'"
              by (simp add: R1_def, force)
            moreover
            ― ‹get the two different cases True and False from semantics:›
            from irange R1def' I1step have case_distinction:
              "RS = [c1]  BMap (E b m1) = True 
              RS = [c2]  BMap (E b m1) = False"
              by (simp, metis MWLf_semantics.MWLfSteps_det_cases(4))
            moreover
              ― ‹Case 1: b evaluates to True›
            {
              assume bevalT: "BMap (E b m1) = True"
              assume RSassump: "RS = [c1]"
              from irange bevalT I1step R1def' RSassump have memeq:
                "m2 = m1"
                by (simp, metis MWLf_semantics.MWLfSteps_det_cases(4))
                             
              from bevalT R1def' dequal have b'evalT: 
                "BMap (E b' m1') = True"
                by (simp add: d_indistinguishable_def)

              hence I2step_case1:
                "if b' then c1' else c2' fi,m1'  [c1'],m1'"
                by (simp add: MWLfSteps_det.iftrue)
              
              with irange dequal RSassump memeq R1def' 
              have case1_concl:
                "RS' m2'. I2!i,m1'  RS',m2' 
                ((RS,RS')  R0  RS ≈⇘dRS')  m2 =⇘dm2'"
                by auto
            }
            moreover
              ― ‹Case 2: b evaluates to False›
            {
              assume bevalF: "BMap (E b m1) = False"
              assume RSassump: "RS = [c2]"
              from irange bevalF I1step R1def' RSassump have memeq:
                "m1 = m2"
                by (simp, metis MWLf_semantics.MWLfSteps_det_cases(4))
                          
              from bevalF R1def' dequal have b'evalF: 
                "BMap (E b' m1') = False"
                by (simp add: d_indistinguishable_def)

              hence I2step_case1:
                "if b' then c1' else c2' fi,m1'  [c2'],m1'"
                by (simp add: MWLfSteps_det.iffalse)
          
              with irange dequal RSassump memeq R1def' 
              have case1_concl:
                "RS' m2'. I2!i,m1'  RS',m2' 
                ((RS,RS')  R0  RS ≈⇘dRS')  m2 =⇘dm2'"
                by auto
            }
            ultimately show
              "RS' m2'. I2!i,m1'  RS',m2' 
               ((RS,RS')  R0  RS ≈⇘dRS')  m2 =⇘dm2'"
              by auto
          qed
            

        have inR2case: "(I1,I2)  R2
           RS' m2'. I2!i,m1'  RS',m2' 
             ((RS,RS')  R0  RS ≈⇘dRS')  m2 =⇘dm2'"
          proof -
            assume inR2: "(I1,I2)  R2"
            then obtain c1 c1' c2 c2' b b' where R2def':
              "I1 = [if b then c1 else c2 fi] 
               I2 = [if b' then c1' else c2' fi] 
              [c1] ≈⇘d[c1']  [c2] ≈⇘d[c2'] 
              ([c1] ≈⇘d[c2]  [c1'] ≈⇘d[c2'])"
              by (simp add: R2_def, force)
            moreover
              ― ‹get the two different cases for the result from semantics:›
            from irange R2def' I1step have case_distinction_left:
              "(RS = [c1]  RS = [c2])  m2 = m1"
              by (simp, metis MWLf_semantics.MWLfSteps_det_cases(4)) 
            moreover
            from irange R2def' dequal obtain RS' where I2step:
              "I2!i,m1'  RS',m1'
               (RS' = [c1']  RS' = [c2'])  m1 =⇘dm1'"
              by (simp, metis MWLfSteps_det.iffalse MWLfSteps_det.iftrue)
            moreover
            from USdBtrans have " [c1] ≈⇘d[c2]; [c2] ≈⇘d[c2']  
               [c1] ≈⇘d[c2']"
              by (unfold trans_def, blast)
            moreover
            from USdBtrans have " [c1] ≈⇘d[c1']; [c1'] ≈⇘d[c2']  
               [c1] ≈⇘d[c2']"
              by (unfold trans_def, blast)
            moreover
            from USdBsym have "[c1] ≈⇘d[c2]  [c2] ≈⇘d[c1]"
              by (simp add: sym_def)
            moreover
            from USdBtrans have " [c2] ≈⇘d[c1]; [c1] ≈⇘d[c1']  
               [c2] ≈⇘d[c1']"    
              by (unfold trans_def, blast)
            moreover
            from USdBsym have "[c1'] ≈⇘d[c2']  [c2'] ≈⇘d[c1']"
              by (simp add: sym_def)
            moreover
            from USdBtrans have " [c2] ≈⇘d[c2']; [c2'] ≈⇘d[c1']  
               [c2] ≈⇘d[c1']"  
              by (unfold trans_def, blast)            
            ultimately show 
             "RS' m2'. I2!i,m1'  RS',m2' 
              ((RS,RS')  R0  RS ≈⇘dRS')  m2 =⇘dm2'"
              by auto
          qed

        from inR0 inR1case inR2case show 
          "RS' m2'. I2!i,m1'  RS',m2' 
          ((RS,RS')  R0  RS ≈⇘dRS')  m2 =⇘dm2'"
          by (auto simp add: R0_def)
        qed
       
  hence "R0  ≈⇘d⇙"
    by (rule Up_To_Technique)
  
  with inR0 show ?thesis
    by auto
  
qed

theorem Compositionality_While:
  assumes dind: "b ≡⇘db'"
  assumes bodyrelated: "[c] ≈⇘d[c']"
  shows "[while b do c od] ≈⇘d[while b' do c' od]"
proof -
  define R1 where "R1 = {(S1,S2). c1 c1' c2 c2' b b' W W'.
    S1 = (c1;(while b do c2 od))#W  
    S2 = (c1';(while b' do c2' od))#W' 
    [c1] ≈⇘d[c1']  [c2] ≈⇘d[c2']  W ≈⇘dW'  b ≡⇘db'}"

  define R2 where "R2 = {(W1,W2). c1 c1' b b'. 
    W1 = [while b do c1 od]  W2 = [while b' do c1' od] 
    [c1] ≈⇘d[c1']  b ≡⇘db'}"

  define R0 where "R0 = R1  R2"

  from dind bodyrelated 
  have inR0: "([while b do c od],[while b' do c' od])  R0"
    by (simp add: R0_def R1_def R2_def)
   
  have uptoR0: "d_Bisimulation_Up_To_USdB d R0"
    proof (simp add: d_Bisimulation_Up_To_USdB_def, auto)
        from USdBsym d_indistinguishable_sym have symR1: "sym R1"
          by (simp add: sym_def R1_def, fastforce)
        from USdBsym d_indistinguishable_sym have symR2: "sym R2"
          by (simp add: sym_def R2_def, fastforce)
        from symR1 symR2 show "sym R0"
          by (simp add: sym_def R0_def)
      next
        fix W1 W2
        assume inR0: "(W1,W2)  R0"
        with USdBeqlen show "length W1 = length W2"
          by (simp add: R0_def R1_def R2_def, force)
      next
        fix W1 W2 i m1 m1' RS m2
        assume inR0: "(W1,W2)  R0"
        assume irange: "i < length W1"
        assume W1step: "W1!i,m1  RS,m2"
        assume dequal: "m1 =⇘dm1'"
       
        from inR0 show "RS' m2'. W2!i,m1'  RS',m2' 
          ((RS,RS')  R0  RS ≈⇘dRS')  m2 =⇘dm2'"
          proof (simp add: R0_def, auto)
            assume inR1: "(W1,W2)  R1"

            then obtain c1 c1' c2 c2' b b' V V'
              where R1def': "W1 = (c1;(while b do c2 od))#V 
               W2 = (c1';(while b' do c2' od))#V'  
              [c1] ≈⇘d[c1']  [c2] ≈⇘d[c2']  V ≈⇘dV'  b ≡⇘db'"
              by (simp add: R1_def, force)

            with irange have case_distinction1: "i = 0 
              (V  []  i  0)"
              by auto
            moreover
            have case1: "i = 0  
              RS' m2'. W2!i,m1'  RS',m2' 
              ((RS,RS')  R1  (RS,RS')  R2  RS ≈⇘dRS')
               m2 =⇘dm2'"
              proof -
                assume i0: "i = 0"
                  ― ‹get the two different sub-cases:›
                with R1def' W1step obtain c3 W where case_distinction: 
                  "RS = [while b do c2 od]  c1,m1  [],m2
                   RS = (c3;(while b do c2 od))#W  c1,m1  c3#W,m2"
                  by (simp, metis MWLfSteps_det_cases(3))
                moreover
                  ― ‹Case 1: first command terminates›
                {
                  assume RSassump: "RS = [while b do c2 od]"
                  assume StepAssump: "c1,m1  [],m2" 

                  from USdBeqlen[of "[]"] StepAssump R1def' 
                    USdB_Strong_d_Bisimulation dequal
                    strongdB_aux[of "d" "≈⇘d⇙" "i"
                    "[c1]" "[c1']" "m1" "[]" "m2" "m1'"] i0
                  obtain W' m2' where c1c1'reason: 
                    "c1',m1'  W',m2'  W' = [] 
                     [] ≈⇘dW'  m2 =⇘dm2'"
                    by fastforce

                  with c1c1'reason have conclpart1:
                    "c1';(while b' do c2' od),m1' 
                     [while b' do c2' od],m2'  m2 =⇘dm2'"
                    by (simp add: MWLfSteps_det.seq1)

                  from R1def' have conclpart2:
                    "([while b do c2 od],[while b' do c2' od])  R2"
                    by (simp add: R2_def)

                  with conclpart1 RSassump i0 R1def'
                  have case1_concl:
                    "RS' m2'. W2!i,m1'  RS',m2' 
                    ((RS,RS')  R1  (RS,RS')  R2  RS ≈⇘dRS')
                     m2 =⇘dm2'"
                    by auto
                }
                moreover
                  ― ‹Case 2: first command does not terminate›
                {
                  assume RSassump: "RS = (c3;(while b do c2 od))#W"
                  assume StepAssump: "c1,m1  c3#W,m2"
              
                  from StepAssump R1def' USdB_Strong_d_Bisimulation dequal
                    strongdB_aux[of "d" "≈⇘d⇙" "i"
                    "[c1]" "[c1']" "m1" "c3#W" "m2" "m1'"] i0 
                  obtain V'' m2' where c1c1'reason: 
                    "c1',m1'  V'',m2' 
                     (c3#W) ≈⇘dV''  m2 =⇘dm2'"
                    by fastforce
 
                  with USdBeqlen[of "c3#W" "V''"] obtain c3' W' 
                    where V''reason: "V'' = c3'#W'"
                    by (cases V'', force, force)
          
                  with c1c1'reason have conclpart1:
                    "c1';(while b' do c2' od),m1'  
                    (c3';(while b' do c2' od))#W',m2' 
                     m2 =⇘dm2'"
                    by (simp add: MWLfSteps_det.seq2)

                  from V''reason 
                    c1c1'reason USdB_decomp_head_tail[of "c3" "W"] 
                    USdB_Strong_d_Bisimulation
                  have c3aWinUSDB: 
                    "[c3] ≈⇘d[c3']  W ≈⇘dW'"
                    by blast
        
                  with R1def' have conclpart2:
                    "((c3;(while b do c2 od))#W,
                       (c3';(while b' do c2' od))#W')  R1"
                    by (simp add: R1_def)

                  with i0 RSassump R1def' V''reason conclpart1 
                  have case2_concl:
                    "RS' m2'. W2!i,m1'  RS',m2' 
                    ((RS,RS')  R1  (RS,RS')  R2  RS ≈⇘dRS')
                     m2 =⇘dm2'"
                    by auto
                } 
                ultimately
                show "RS' m2'. W2!i,m1'  RS',m2' 
                  ((RS,RS')  R1  (RS,RS')  R2  RS ≈⇘dRS')
                   m2 =⇘dm2'"
                  by blast
              qed
              moreover
              have case2: " V  []; i  0 
                 RS' m2'. W2!i,m1'  RS',m2' 
                ((RS,RS')  R1  (RS,RS')  R2  RS ≈⇘dRS')
                 m2 =⇘dm2'"
              proof - 
                assume Vnonempt: "V  []"
                assume inot0: "i  0"

                with Vnonempt irange R1def' have i1range:
                  "(i-Suc 0) < length V"
                  by simp

                from inot0 R1def' have W1ieq: "W1!i = V!(i-Suc 0)"
                  by auto

                from inot0 R1def' have "W2!i = V'!(i-Suc 0)"
                  by auto
              
                with W1ieq R1def' W1step i1range dequal 
                  USdB_Strong_d_Bisimulation
                  strongdB_aux[of "d" "USdB d"
                  "i-Suc 0" "V" "V'" "m1" "RS" "m2" "m1'"]
                show "RS' m2'. W2!i,m1'  RS',m2' 
                  ((RS,RS')  R1  (RS,RS')  R2  RS ≈⇘dRS')
                   m2 =⇘dm2'"
                  by force
              qed
              ultimately show "RS' m2'. W2!i,m1'  RS',m2' 
                ((RS,RS')  R1  (RS,RS')  R2  RS ≈⇘dRS') 
                 m2 =⇘dm2'"
                by auto
            next          
              assume inR2: "(W1,W2)  R2"

              then obtain c1 c1' b b' where R2def': 
                "W1 = [while b do c1 od]  W2 = [while b' do c1' od] 
                [c1] ≈⇘d[c1']  b ≡⇘db'"
                by (auto simp add: R2_def)
                ― ‹get the two different cases:›
              moreover
              from irange R2def' W1step have case_distinction:
                "RS = [c1;(while b do c1 od)]  BMap (E b m1) = True 
                RS = []  BMap (E b m1) = False"
                by (simp,metis MWLf_semantics.MWLfSteps_det_cases(5))
              moreover
                ― ‹Case 1: b evaluates to True›
              {
                assume bevalT: "BMap (E b m1)"
                assume RSassump: "RS = [c1;(while b do c1 od)]"
                from irange bevalT W1step R2def' RSassump have memeq:
                  "m2 = m1"
                  by (simp,metis MWLf_semantics.MWLfSteps_det_cases(5))
          
                from bevalT R2def' dequal have b'evalT: "BMap (E b' m1')"
                  by (simp add: d_indistinguishable_def)

                hence W2step_case1: 
                  "while b' do c1' od,m1' 
                     [c1';(while b' do c1' od)],m1'"
                  by (simp add: MWLfSteps_det.whiletrue)

                from trivialpair_in_USdB R2def' have inWR2: 
                  "([c1;(while b do c1 od)],
                     [c1';(while b' do c1' od)])  R1"
                  by (auto simp add: R1_def)

                with irange dequal RSassump memeq W2step_case1 R2def' 
                have case1_concl:
                  "RS' m2'. W2!i,m1'  RS',m2' 
                  ((RS,RS')  R1  (RS,RS')  R2  RS ≈⇘dRS')
                   m2 =⇘dm2'"
                  by auto
              }
              moreover
                ― ‹Case 2: b evaluates to False›
              {
                assume bevalF: "BMap (E b m1) = False"
                assume RSassump: "RS = []"
                from irange bevalF W1step R2def' RSassump have memeq:
                  "m2 = m1"
                  by (simp,metis MWLf_semantics.MWLfSteps_det_cases(5))

                from bevalF R2def' dequal have b'equalF: 
                  "BMap (E b' m1') = False"
                  by (simp add: d_indistinguishable_def)
          
                hence W2step_case2:
                  "while b' do c1' od,m1'  [],m1'"
                  by (simp add: MWLfSteps_det.whilefalse)
          
                with trivialpair_in_USdB irange dequal RSassump 
                  memeq R2def' 
                have case1_concl:
                  "RS' m2'. W2!i,m1'  RS',m2' 
                  ((RS,RS')  R1  (RS,RS')  R2  RS ≈⇘dRS')
                   m2 =⇘dm2'"
                  by force
              }
              ultimately
              show "RS' m2'. W2!i,m1'  RS',m2' 
                ((RS,RS')  R1  (RS,RS')  R2  RS ≈⇘dRS')
                 m2 =⇘dm2'"
                by auto
            qed
          qed
                  
  hence "R0  ≈⇘d⇙"
    by (rule Up_To_Technique)
  
  with inR0 show ?thesis
    by auto
  
qed

end 

end