src/HOL/Imperative_HOL/ex/Imperative_Quicksort.thy
changeset 40671 5e46057ba8e0
parent 38058 e4640c2ceb43
child 41413 64cd30d6b0b8
equal deleted inserted replaced
40630:3b5c31e55540 40671:5e46057ba8e0
    19        Array.upd i y arr;
    19        Array.upd i y arr;
    20        Array.upd j x arr;
    20        Array.upd j x arr;
    21        return ()
    21        return ()
    22      }"
    22      }"
    23 
    23 
    24 lemma crel_swapI [crel_intros]:
    24 lemma effect_swapI [effect_intros]:
    25   assumes "i < Array.length h a" "j < Array.length h a"
    25   assumes "i < Array.length h a" "j < Array.length h a"
    26     "x = Array.get h a ! i" "y = Array.get h a ! j"
    26     "x = Array.get h a ! i" "y = Array.get h a ! j"
    27     "h' = Array.update a j x (Array.update a i y h)"
    27     "h' = Array.update a j x (Array.update a i y h)"
    28   shows "crel (swap a i j) h h' r"
    28   shows "effect (swap a i j) h h' r"
    29   unfolding swap_def using assms by (auto intro!: crel_intros)
    29   unfolding swap_def using assms by (auto intro!: effect_intros)
    30 
    30 
    31 lemma swap_permutes:
    31 lemma swap_permutes:
    32   assumes "crel (swap a i j) h h' rs"
    32   assumes "effect (swap a i j) h h' rs"
    33   shows "multiset_of (Array.get h' a) 
    33   shows "multiset_of (Array.get h' a) 
    34   = multiset_of (Array.get h a)"
    34   = multiset_of (Array.get h a)"
    35   using assms
    35   using assms
    36   unfolding swap_def
    36   unfolding swap_def
    37   by (auto simp add: Array.length_def multiset_of_swap dest: sym [of _ "h'"] elim!: crel_bindE crel_nthE crel_returnE crel_updE)
    37   by (auto simp add: Array.length_def multiset_of_swap dest: sym [of _ "h'"] elim!: effect_bindE effect_nthE effect_returnE effect_updE)
    38 
    38 
    39 function part1 :: "nat array \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> nat Heap"
    39 function part1 :: "nat array \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> nat Heap"
    40 where
    40 where
    41   "part1 a left right p = (
    41   "part1 a left right p = (
    42      if (right \<le> left) then return right
    42      if (right \<le> left) then return right
    52 by (relation "measure (\<lambda>(_,l,r,_). r - l )") auto
    52 by (relation "measure (\<lambda>(_,l,r,_). r - l )") auto
    53 
    53 
    54 declare part1.simps[simp del]
    54 declare part1.simps[simp del]
    55 
    55 
    56 lemma part_permutes:
    56 lemma part_permutes:
    57   assumes "crel (part1 a l r p) h h' rs"
    57   assumes "effect (part1 a l r p) h h' rs"
    58   shows "multiset_of (Array.get h' a) 
    58   shows "multiset_of (Array.get h' a) 
    59   = multiset_of (Array.get h a)"
    59   = multiset_of (Array.get h a)"
    60   using assms
    60   using assms
    61 proof (induct a l r p arbitrary: h h' rs rule:part1.induct)
    61 proof (induct a l r p arbitrary: h h' rs rule:part1.induct)
    62   case (1 a l r p h h' rs)
    62   case (1 a l r p h h' rs)
    63   thus ?case
    63   thus ?case
    64     unfolding part1.simps [of a l r p]
    64     unfolding part1.simps [of a l r p]
    65     by (elim crel_bindE crel_ifE crel_returnE crel_nthE) (auto simp add: swap_permutes)
    65     by (elim effect_bindE effect_ifE effect_returnE effect_nthE) (auto simp add: swap_permutes)
    66 qed
    66 qed
    67 
    67 
    68 lemma part_returns_index_in_bounds:
    68 lemma part_returns_index_in_bounds:
    69   assumes "crel (part1 a l r p) h h' rs"
    69   assumes "effect (part1 a l r p) h h' rs"
    70   assumes "l \<le> r"
    70   assumes "l \<le> r"
    71   shows "l \<le> rs \<and> rs \<le> r"
    71   shows "l \<le> rs \<and> rs \<le> r"
    72 using assms
    72 using assms
    73 proof (induct a l r p arbitrary: h h' rs rule:part1.induct)
    73 proof (induct a l r p arbitrary: h h' rs rule:part1.induct)
    74   case (1 a l r p h h' rs)
    74   case (1 a l r p h h' rs)
    75   note cr = `crel (part1 a l r p) h h' rs`
    75   note cr = `effect (part1 a l r p) h h' rs`
    76   show ?case
    76   show ?case
    77   proof (cases "r \<le> l")
    77   proof (cases "r \<le> l")
    78     case True (* Terminating case *)
    78     case True (* Terminating case *)
    79     with cr `l \<le> r` show ?thesis
    79     with cr `l \<le> r` show ?thesis
    80       unfolding part1.simps[of a l r p]
    80       unfolding part1.simps[of a l r p]
    81       by (elim crel_bindE crel_ifE crel_returnE crel_nthE) auto
    81       by (elim effect_bindE effect_ifE effect_returnE effect_nthE) auto
    82   next
    82   next
    83     case False (* recursive case *)
    83     case False (* recursive case *)
    84     note rec_condition = this
    84     note rec_condition = this
    85     let ?v = "Array.get h a ! l"
    85     let ?v = "Array.get h a ! l"
    86     show ?thesis
    86     show ?thesis
    87     proof (cases "?v \<le> p")
    87     proof (cases "?v \<le> p")
    88       case True
    88       case True
    89       with cr False
    89       with cr False
    90       have rec1: "crel (part1 a (l + 1) r p) h h' rs"
    90       have rec1: "effect (part1 a (l + 1) r p) h h' rs"
    91         unfolding part1.simps[of a l r p]
    91         unfolding part1.simps[of a l r p]
    92         by (elim crel_bindE crel_nthE crel_ifE crel_returnE) auto
    92         by (elim effect_bindE effect_nthE effect_ifE effect_returnE) auto
    93       from rec_condition have "l + 1 \<le> r" by arith
    93       from rec_condition have "l + 1 \<le> r" by arith
    94       from 1(1)[OF rec_condition True rec1 `l + 1 \<le> r`]
    94       from 1(1)[OF rec_condition True rec1 `l + 1 \<le> r`]
    95       show ?thesis by simp
    95       show ?thesis by simp
    96     next
    96     next
    97       case False
    97       case False
    98       with rec_condition cr
    98       with rec_condition cr
    99       obtain h1 where swp: "crel (swap a l r) h h1 ()"
    99       obtain h1 where swp: "effect (swap a l r) h h1 ()"
   100         and rec2: "crel (part1 a l (r - 1) p) h1 h' rs"
   100         and rec2: "effect (part1 a l (r - 1) p) h1 h' rs"
   101         unfolding part1.simps[of a l r p]
   101         unfolding part1.simps[of a l r p]
   102         by (elim crel_bindE crel_nthE crel_ifE crel_returnE) auto
   102         by (elim effect_bindE effect_nthE effect_ifE effect_returnE) auto
   103       from rec_condition have "l \<le> r - 1" by arith
   103       from rec_condition have "l \<le> r - 1" by arith
   104       from 1(2) [OF rec_condition False rec2 `l \<le> r - 1`] show ?thesis by fastsimp
   104       from 1(2) [OF rec_condition False rec2 `l \<le> r - 1`] show ?thesis by fastsimp
   105     qed
   105     qed
   106   qed
   106   qed
   107 qed
   107 qed
   108 
   108 
   109 lemma part_length_remains:
   109 lemma part_length_remains:
   110   assumes "crel (part1 a l r p) h h' rs"
   110   assumes "effect (part1 a l r p) h h' rs"
   111   shows "Array.length h a = Array.length h' a"
   111   shows "Array.length h a = Array.length h' a"
   112 using assms
   112 using assms
   113 proof (induct a l r p arbitrary: h h' rs rule:part1.induct)
   113 proof (induct a l r p arbitrary: h h' rs rule:part1.induct)
   114   case (1 a l r p h h' rs)
   114   case (1 a l r p h h' rs)
   115   note cr = `crel (part1 a l r p) h h' rs`
   115   note cr = `effect (part1 a l r p) h h' rs`
   116   
   116   
   117   show ?case
   117   show ?case
   118   proof (cases "r \<le> l")
   118   proof (cases "r \<le> l")
   119     case True (* Terminating case *)
   119     case True (* Terminating case *)
   120     with cr show ?thesis
   120     with cr show ?thesis
   121       unfolding part1.simps[of a l r p]
   121       unfolding part1.simps[of a l r p]
   122       by (elim crel_bindE crel_ifE crel_returnE crel_nthE) auto
   122       by (elim effect_bindE effect_ifE effect_returnE effect_nthE) auto
   123   next
   123   next
   124     case False (* recursive case *)
   124     case False (* recursive case *)
   125     with cr 1 show ?thesis
   125     with cr 1 show ?thesis
   126       unfolding part1.simps [of a l r p] swap_def
   126       unfolding part1.simps [of a l r p] swap_def
   127       by (auto elim!: crel_bindE crel_ifE crel_nthE crel_returnE crel_updE) fastsimp
   127       by (auto elim!: effect_bindE effect_ifE effect_nthE effect_returnE effect_updE) fastsimp
   128   qed
   128   qed
   129 qed
   129 qed
   130 
   130 
   131 lemma part_outer_remains:
   131 lemma part_outer_remains:
   132   assumes "crel (part1 a l r p) h h' rs"
   132   assumes "effect (part1 a l r p) h h' rs"
   133   shows "\<forall>i. i < l \<or> r < i \<longrightarrow> Array.get h (a::nat array) ! i = Array.get h' a ! i"
   133   shows "\<forall>i. i < l \<or> r < i \<longrightarrow> Array.get h (a::nat array) ! i = Array.get h' a ! i"
   134   using assms
   134   using assms
   135 proof (induct a l r p arbitrary: h h' rs rule:part1.induct)
   135 proof (induct a l r p arbitrary: h h' rs rule:part1.induct)
   136   case (1 a l r p h h' rs)
   136   case (1 a l r p h h' rs)
   137   note cr = `crel (part1 a l r p) h h' rs`
   137   note cr = `effect (part1 a l r p) h h' rs`
   138   
   138   
   139   show ?case
   139   show ?case
   140   proof (cases "r \<le> l")
   140   proof (cases "r \<le> l")
   141     case True (* Terminating case *)
   141     case True (* Terminating case *)
   142     with cr show ?thesis
   142     with cr show ?thesis
   143       unfolding part1.simps[of a l r p]
   143       unfolding part1.simps[of a l r p]
   144       by (elim crel_bindE crel_ifE crel_returnE crel_nthE) auto
   144       by (elim effect_bindE effect_ifE effect_returnE effect_nthE) auto
   145   next
   145   next
   146     case False (* recursive case *)
   146     case False (* recursive case *)
   147     note rec_condition = this
   147     note rec_condition = this
   148     let ?v = "Array.get h a ! l"
   148     let ?v = "Array.get h a ! l"
   149     show ?thesis
   149     show ?thesis
   150     proof (cases "?v \<le> p")
   150     proof (cases "?v \<le> p")
   151       case True
   151       case True
   152       with cr False
   152       with cr False
   153       have rec1: "crel (part1 a (l + 1) r p) h h' rs"
   153       have rec1: "effect (part1 a (l + 1) r p) h h' rs"
   154         unfolding part1.simps[of a l r p]
   154         unfolding part1.simps[of a l r p]
   155         by (elim crel_bindE crel_nthE crel_ifE crel_returnE) auto
   155         by (elim effect_bindE effect_nthE effect_ifE effect_returnE) auto
   156       from 1(1)[OF rec_condition True rec1]
   156       from 1(1)[OF rec_condition True rec1]
   157       show ?thesis by fastsimp
   157       show ?thesis by fastsimp
   158     next
   158     next
   159       case False
   159       case False
   160       with rec_condition cr
   160       with rec_condition cr
   161       obtain h1 where swp: "crel (swap a l r) h h1 ()"
   161       obtain h1 where swp: "effect (swap a l r) h h1 ()"
   162         and rec2: "crel (part1 a l (r - 1) p) h1 h' rs"
   162         and rec2: "effect (part1 a l (r - 1) p) h1 h' rs"
   163         unfolding part1.simps[of a l r p]
   163         unfolding part1.simps[of a l r p]
   164         by (elim crel_bindE crel_nthE crel_ifE crel_returnE) auto
   164         by (elim effect_bindE effect_nthE effect_ifE effect_returnE) auto
   165       from swp rec_condition have
   165       from swp rec_condition have
   166         "\<forall>i. i < l \<or> r < i \<longrightarrow> Array.get h a ! i = Array.get h1 a ! i"
   166         "\<forall>i. i < l \<or> r < i \<longrightarrow> Array.get h a ! i = Array.get h1 a ! i"
   167         unfolding swap_def
   167         unfolding swap_def
   168         by (elim crel_bindE crel_nthE crel_updE crel_returnE) auto
   168         by (elim effect_bindE effect_nthE effect_updE effect_returnE) auto
   169       with 1(2) [OF rec_condition False rec2] show ?thesis by fastsimp
   169       with 1(2) [OF rec_condition False rec2] show ?thesis by fastsimp
   170     qed
   170     qed
   171   qed
   171   qed
   172 qed
   172 qed
   173 
   173 
   174 
   174 
   175 lemma part_partitions:
   175 lemma part_partitions:
   176   assumes "crel (part1 a l r p) h h' rs"
   176   assumes "effect (part1 a l r p) h h' rs"
   177   shows "(\<forall>i. l \<le> i \<and> i < rs \<longrightarrow> Array.get h' (a::nat array) ! i \<le> p)
   177   shows "(\<forall>i. l \<le> i \<and> i < rs \<longrightarrow> Array.get h' (a::nat array) ! i \<le> p)
   178   \<and> (\<forall>i. rs < i \<and> i \<le> r \<longrightarrow> Array.get h' a ! i \<ge> p)"
   178   \<and> (\<forall>i. rs < i \<and> i \<le> r \<longrightarrow> Array.get h' a ! i \<ge> p)"
   179   using assms
   179   using assms
   180 proof (induct a l r p arbitrary: h h' rs rule:part1.induct)
   180 proof (induct a l r p arbitrary: h h' rs rule:part1.induct)
   181   case (1 a l r p h h' rs)
   181   case (1 a l r p h h' rs)
   182   note cr = `crel (part1 a l r p) h h' rs`
   182   note cr = `effect (part1 a l r p) h h' rs`
   183   
   183   
   184   show ?case
   184   show ?case
   185   proof (cases "r \<le> l")
   185   proof (cases "r \<le> l")
   186     case True (* Terminating case *)
   186     case True (* Terminating case *)
   187     with cr have "rs = r"
   187     with cr have "rs = r"
   188       unfolding part1.simps[of a l r p]
   188       unfolding part1.simps[of a l r p]
   189       by (elim crel_bindE crel_ifE crel_returnE crel_nthE) auto
   189       by (elim effect_bindE effect_ifE effect_returnE effect_nthE) auto
   190     with True
   190     with True
   191     show ?thesis by auto
   191     show ?thesis by auto
   192   next
   192   next
   193     case False (* recursive case *)
   193     case False (* recursive case *)
   194     note lr = this
   194     note lr = this
   195     let ?v = "Array.get h a ! l"
   195     let ?v = "Array.get h a ! l"
   196     show ?thesis
   196     show ?thesis
   197     proof (cases "?v \<le> p")
   197     proof (cases "?v \<le> p")
   198       case True
   198       case True
   199       with lr cr
   199       with lr cr
   200       have rec1: "crel (part1 a (l + 1) r p) h h' rs"
   200       have rec1: "effect (part1 a (l + 1) r p) h h' rs"
   201         unfolding part1.simps[of a l r p]
   201         unfolding part1.simps[of a l r p]
   202         by (elim crel_bindE crel_nthE crel_ifE crel_returnE) auto
   202         by (elim effect_bindE effect_nthE effect_ifE effect_returnE) auto
   203       from True part_outer_remains[OF rec1] have a_l: "Array.get h' a ! l \<le> p"
   203       from True part_outer_remains[OF rec1] have a_l: "Array.get h' a ! l \<le> p"
   204         by fastsimp
   204         by fastsimp
   205       have "\<forall>i. (l \<le> i = (l = i \<or> Suc l \<le> i))" by arith
   205       have "\<forall>i. (l \<le> i = (l = i \<or> Suc l \<le> i))" by arith
   206       with 1(1)[OF False True rec1] a_l show ?thesis
   206       with 1(1)[OF False True rec1] a_l show ?thesis
   207         by auto
   207         by auto
   208     next
   208     next
   209       case False
   209       case False
   210       with lr cr
   210       with lr cr
   211       obtain h1 where swp: "crel (swap a l r) h h1 ()"
   211       obtain h1 where swp: "effect (swap a l r) h h1 ()"
   212         and rec2: "crel (part1 a l (r - 1) p) h1 h' rs"
   212         and rec2: "effect (part1 a l (r - 1) p) h1 h' rs"
   213         unfolding part1.simps[of a l r p]
   213         unfolding part1.simps[of a l r p]
   214         by (elim crel_bindE crel_nthE crel_ifE crel_returnE) auto
   214         by (elim effect_bindE effect_nthE effect_ifE effect_returnE) auto
   215       from swp False have "Array.get h1 a ! r \<ge> p"
   215       from swp False have "Array.get h1 a ! r \<ge> p"
   216         unfolding swap_def
   216         unfolding swap_def
   217         by (auto simp add: Array.length_def elim!: crel_bindE crel_nthE crel_updE crel_returnE)
   217         by (auto simp add: Array.length_def elim!: effect_bindE effect_nthE effect_updE effect_returnE)
   218       with part_outer_remains [OF rec2] lr have a_r: "Array.get h' a ! r \<ge> p"
   218       with part_outer_remains [OF rec2] lr have a_r: "Array.get h' a ! r \<ge> p"
   219         by fastsimp
   219         by fastsimp
   220       have "\<forall>i. (i \<le> r = (i = r \<or> i \<le> r - 1))" by arith
   220       have "\<forall>i. (i \<le> r = (i = r \<or> i \<le> r - 1))" by arith
   221       with 1(2)[OF lr False rec2] a_r show ?thesis
   221       with 1(2)[OF lr False rec2] a_r show ?thesis
   222         by auto
   222         by auto
   237    }"
   237    }"
   238 
   238 
   239 declare partition.simps[simp del]
   239 declare partition.simps[simp del]
   240 
   240 
   241 lemma partition_permutes:
   241 lemma partition_permutes:
   242   assumes "crel (partition a l r) h h' rs"
   242   assumes "effect (partition a l r) h h' rs"
   243   shows "multiset_of (Array.get h' a) 
   243   shows "multiset_of (Array.get h' a) 
   244   = multiset_of (Array.get h a)"
   244   = multiset_of (Array.get h a)"
   245 proof -
   245 proof -
   246     from assms part_permutes swap_permutes show ?thesis
   246     from assms part_permutes swap_permutes show ?thesis
   247       unfolding partition.simps
   247       unfolding partition.simps
   248       by (elim crel_bindE crel_returnE crel_nthE crel_ifE crel_updE) auto
   248       by (elim effect_bindE effect_returnE effect_nthE effect_ifE effect_updE) auto
   249 qed
   249 qed
   250 
   250 
   251 lemma partition_length_remains:
   251 lemma partition_length_remains:
   252   assumes "crel (partition a l r) h h' rs"
   252   assumes "effect (partition a l r) h h' rs"
   253   shows "Array.length h a = Array.length h' a"
   253   shows "Array.length h a = Array.length h' a"
   254 proof -
   254 proof -
   255   from assms part_length_remains show ?thesis
   255   from assms part_length_remains show ?thesis
   256     unfolding partition.simps swap_def
   256     unfolding partition.simps swap_def
   257     by (elim crel_bindE crel_returnE crel_nthE crel_ifE crel_updE) auto
   257     by (elim effect_bindE effect_returnE effect_nthE effect_ifE effect_updE) auto
   258 qed
   258 qed
   259 
   259 
   260 lemma partition_outer_remains:
   260 lemma partition_outer_remains:
   261   assumes "crel (partition a l r) h h' rs"
   261   assumes "effect (partition a l r) h h' rs"
   262   assumes "l < r"
   262   assumes "l < r"
   263   shows "\<forall>i. i < l \<or> r < i \<longrightarrow> Array.get h (a::nat array) ! i = Array.get h' a ! i"
   263   shows "\<forall>i. i < l \<or> r < i \<longrightarrow> Array.get h (a::nat array) ! i = Array.get h' a ! i"
   264 proof -
   264 proof -
   265   from assms part_outer_remains part_returns_index_in_bounds show ?thesis
   265   from assms part_outer_remains part_returns_index_in_bounds show ?thesis
   266     unfolding partition.simps swap_def
   266     unfolding partition.simps swap_def
   267     by (elim crel_bindE crel_returnE crel_nthE crel_ifE crel_updE) fastsimp
   267     by (elim effect_bindE effect_returnE effect_nthE effect_ifE effect_updE) fastsimp
   268 qed
   268 qed
   269 
   269 
   270 lemma partition_returns_index_in_bounds:
   270 lemma partition_returns_index_in_bounds:
   271   assumes crel: "crel (partition a l r) h h' rs"
   271   assumes effect: "effect (partition a l r) h h' rs"
   272   assumes "l < r"
   272   assumes "l < r"
   273   shows "l \<le> rs \<and> rs \<le> r"
   273   shows "l \<le> rs \<and> rs \<le> r"
   274 proof -
   274 proof -
   275   from crel obtain middle h'' p where part: "crel (part1 a l (r - 1) p) h h'' middle"
   275   from effect obtain middle h'' p where part: "effect (part1 a l (r - 1) p) h h'' middle"
   276     and rs_equals: "rs = (if Array.get h'' a ! middle \<le> Array.get h a ! r then middle + 1
   276     and rs_equals: "rs = (if Array.get h'' a ! middle \<le> Array.get h a ! r then middle + 1
   277          else middle)"
   277          else middle)"
   278     unfolding partition.simps
   278     unfolding partition.simps
   279     by (elim crel_bindE crel_returnE crel_nthE crel_ifE crel_updE) simp 
   279     by (elim effect_bindE effect_returnE effect_nthE effect_ifE effect_updE) simp 
   280   from `l < r` have "l \<le> r - 1" by arith
   280   from `l < r` have "l \<le> r - 1" by arith
   281   from part_returns_index_in_bounds[OF part this] rs_equals `l < r` show ?thesis by auto
   281   from part_returns_index_in_bounds[OF part this] rs_equals `l < r` show ?thesis by auto
   282 qed
   282 qed
   283 
   283 
   284 lemma partition_partitions:
   284 lemma partition_partitions:
   285   assumes crel: "crel (partition a l r) h h' rs"
   285   assumes effect: "effect (partition a l r) h h' rs"
   286   assumes "l < r"
   286   assumes "l < r"
   287   shows "(\<forall>i. l \<le> i \<and> i < rs \<longrightarrow> Array.get h' (a::nat array) ! i \<le> Array.get h' a ! rs) \<and>
   287   shows "(\<forall>i. l \<le> i \<and> i < rs \<longrightarrow> Array.get h' (a::nat array) ! i \<le> Array.get h' a ! rs) \<and>
   288   (\<forall>i. rs < i \<and> i \<le> r \<longrightarrow> Array.get h' a ! rs \<le> Array.get h' a ! i)"
   288   (\<forall>i. rs < i \<and> i \<le> r \<longrightarrow> Array.get h' a ! rs \<le> Array.get h' a ! i)"
   289 proof -
   289 proof -
   290   let ?pivot = "Array.get h a ! r" 
   290   let ?pivot = "Array.get h a ! r" 
   291   from crel obtain middle h1 where part: "crel (part1 a l (r - 1) ?pivot) h h1 middle"
   291   from effect obtain middle h1 where part: "effect (part1 a l (r - 1) ?pivot) h h1 middle"
   292     and swap: "crel (swap a rs r) h1 h' ()"
   292     and swap: "effect (swap a rs r) h1 h' ()"
   293     and rs_equals: "rs = (if Array.get h1 a ! middle \<le> ?pivot then middle + 1
   293     and rs_equals: "rs = (if Array.get h1 a ! middle \<le> ?pivot then middle + 1
   294          else middle)"
   294          else middle)"
   295     unfolding partition.simps
   295     unfolding partition.simps
   296     by (elim crel_bindE crel_returnE crel_nthE crel_ifE crel_updE) simp
   296     by (elim effect_bindE effect_returnE effect_nthE effect_ifE effect_updE) simp
   297   from swap have h'_def: "h' = Array.update a r (Array.get h1 a ! rs)
   297   from swap have h'_def: "h' = Array.update a r (Array.get h1 a ! rs)
   298     (Array.update a rs (Array.get h1 a ! r) h1)"
   298     (Array.update a rs (Array.get h1 a ! r) h1)"
   299     unfolding swap_def
   299     unfolding swap_def
   300     by (elim crel_bindE crel_returnE crel_nthE crel_updE) simp
   300     by (elim effect_bindE effect_returnE effect_nthE effect_updE) simp
   301   from swap have in_bounds: "r < Array.length h1 a \<and> rs < Array.length h1 a"
   301   from swap have in_bounds: "r < Array.length h1 a \<and> rs < Array.length h1 a"
   302     unfolding swap_def
   302     unfolding swap_def
   303     by (elim crel_bindE crel_returnE crel_nthE crel_updE) simp
   303     by (elim effect_bindE effect_returnE effect_nthE effect_updE) simp
   304   from swap have swap_length_remains: "Array.length h1 a = Array.length h' a"
   304   from swap have swap_length_remains: "Array.length h1 a = Array.length h' a"
   305     unfolding swap_def by (elim crel_bindE crel_returnE crel_nthE crel_updE) auto
   305     unfolding swap_def by (elim effect_bindE effect_returnE effect_nthE effect_updE) auto
   306   from `l < r` have "l \<le> r - 1" by simp
   306   from `l < r` have "l \<le> r - 1" by simp
   307   note middle_in_bounds = part_returns_index_in_bounds[OF part this]
   307   note middle_in_bounds = part_returns_index_in_bounds[OF part this]
   308   from part_outer_remains[OF part] `l < r`
   308   from part_outer_remains[OF part] `l < r`
   309   have "Array.get h a ! r = Array.get h1 a ! r"
   309   have "Array.get h a ! r = Array.get h1 a ! r"
   310     by fastsimp
   310     by fastsimp
   311   with swap
   311   with swap
   312   have right_remains: "Array.get h a ! r = Array.get h' a ! rs"
   312   have right_remains: "Array.get h a ! r = Array.get h' a ! rs"
   313     unfolding swap_def
   313     unfolding swap_def
   314     by (auto simp add: Array.length_def elim!: crel_bindE crel_returnE crel_nthE crel_updE) (cases "r = rs", auto)
   314     by (auto simp add: Array.length_def elim!: effect_bindE effect_returnE effect_nthE effect_updE) (cases "r = rs", auto)
   315   from part_partitions [OF part]
   315   from part_partitions [OF part]
   316   show ?thesis
   316   show ?thesis
   317   proof (cases "Array.get h1 a ! middle \<le> ?pivot")
   317   proof (cases "Array.get h1 a ! middle \<le> ?pivot")
   318     case True
   318     case True
   319     with rs_equals have rs_equals: "rs = middle + 1" by simp
   319     with rs_equals have rs_equals: "rs = middle + 1" by simp
   417 
   417 
   418 declare quicksort.simps[simp del]
   418 declare quicksort.simps[simp del]
   419 
   419 
   420 
   420 
   421 lemma quicksort_permutes:
   421 lemma quicksort_permutes:
   422   assumes "crel (quicksort a l r) h h' rs"
   422   assumes "effect (quicksort a l r) h h' rs"
   423   shows "multiset_of (Array.get h' a) 
   423   shows "multiset_of (Array.get h' a) 
   424   = multiset_of (Array.get h a)"
   424   = multiset_of (Array.get h a)"
   425   using assms
   425   using assms
   426 proof (induct a l r arbitrary: h h' rs rule: quicksort.induct)
   426 proof (induct a l r arbitrary: h h' rs rule: quicksort.induct)
   427   case (1 a l r h h' rs)
   427   case (1 a l r h h' rs)
   428   with partition_permutes show ?case
   428   with partition_permutes show ?case
   429     unfolding quicksort.simps [of a l r]
   429     unfolding quicksort.simps [of a l r]
   430     by (elim crel_ifE crel_bindE crel_assertE crel_returnE) auto
   430     by (elim effect_ifE effect_bindE effect_assertE effect_returnE) auto
   431 qed
   431 qed
   432 
   432 
   433 lemma length_remains:
   433 lemma length_remains:
   434   assumes "crel (quicksort a l r) h h' rs"
   434   assumes "effect (quicksort a l r) h h' rs"
   435   shows "Array.length h a = Array.length h' a"
   435   shows "Array.length h a = Array.length h' a"
   436 using assms
   436 using assms
   437 proof (induct a l r arbitrary: h h' rs rule: quicksort.induct)
   437 proof (induct a l r arbitrary: h h' rs rule: quicksort.induct)
   438   case (1 a l r h h' rs)
   438   case (1 a l r h h' rs)
   439   with partition_length_remains show ?case
   439   with partition_length_remains show ?case
   440     unfolding quicksort.simps [of a l r]
   440     unfolding quicksort.simps [of a l r]
   441     by (elim crel_ifE crel_bindE crel_assertE crel_returnE) auto
   441     by (elim effect_ifE effect_bindE effect_assertE effect_returnE) auto
   442 qed
   442 qed
   443 
   443 
   444 lemma quicksort_outer_remains:
   444 lemma quicksort_outer_remains:
   445   assumes "crel (quicksort a l r) h h' rs"
   445   assumes "effect (quicksort a l r) h h' rs"
   446    shows "\<forall>i. i < l \<or> r < i \<longrightarrow> Array.get h (a::nat array) ! i = Array.get h' a ! i"
   446    shows "\<forall>i. i < l \<or> r < i \<longrightarrow> Array.get h (a::nat array) ! i = Array.get h' a ! i"
   447   using assms
   447   using assms
   448 proof (induct a l r arbitrary: h h' rs rule: quicksort.induct)
   448 proof (induct a l r arbitrary: h h' rs rule: quicksort.induct)
   449   case (1 a l r h h' rs)
   449   case (1 a l r h h' rs)
   450   note cr = `crel (quicksort a l r) h h' rs`
   450   note cr = `effect (quicksort a l r) h h' rs`
   451   thus ?case
   451   thus ?case
   452   proof (cases "r > l")
   452   proof (cases "r > l")
   453     case False
   453     case False
   454     with cr have "h' = h"
   454     with cr have "h' = h"
   455       unfolding quicksort.simps [of a l r]
   455       unfolding quicksort.simps [of a l r]
   456       by (elim crel_ifE crel_returnE) auto
   456       by (elim effect_ifE effect_returnE) auto
   457     thus ?thesis by simp
   457     thus ?thesis by simp
   458   next
   458   next
   459   case True
   459   case True
   460    { 
   460    { 
   461       fix h1 h2 p ret1 ret2 i
   461       fix h1 h2 p ret1 ret2 i
   462       assume part: "crel (partition a l r) h h1 p"
   462       assume part: "effect (partition a l r) h h1 p"
   463       assume qs1: "crel (quicksort a l (p - 1)) h1 h2 ret1"
   463       assume qs1: "effect (quicksort a l (p - 1)) h1 h2 ret1"
   464       assume qs2: "crel (quicksort a (p + 1) r) h2 h' ret2"
   464       assume qs2: "effect (quicksort a (p + 1) r) h2 h' ret2"
   465       assume pivot: "l \<le> p \<and> p \<le> r"
   465       assume pivot: "l \<le> p \<and> p \<le> r"
   466       assume i_outer: "i < l \<or> r < i"
   466       assume i_outer: "i < l \<or> r < i"
   467       from  partition_outer_remains [OF part True] i_outer
   467       from  partition_outer_remains [OF part True] i_outer
   468       have "Array.get h a !i = Array.get h1 a ! i" by fastsimp
   468       have "Array.get h a !i = Array.get h1 a ! i" by fastsimp
   469       moreover
   469       moreover
   474       have "Array.get h2 a ! i = Array.get h' a ! i" by auto
   474       have "Array.get h2 a ! i = Array.get h' a ! i" by auto
   475       ultimately have "Array.get h a ! i= Array.get h' a ! i" by simp
   475       ultimately have "Array.get h a ! i= Array.get h' a ! i" by simp
   476     }
   476     }
   477     with cr show ?thesis
   477     with cr show ?thesis
   478       unfolding quicksort.simps [of a l r]
   478       unfolding quicksort.simps [of a l r]
   479       by (elim crel_ifE crel_bindE crel_assertE crel_returnE) auto
   479       by (elim effect_ifE effect_bindE effect_assertE effect_returnE) auto
   480   qed
   480   qed
   481 qed
   481 qed
   482 
   482 
   483 lemma quicksort_is_skip:
   483 lemma quicksort_is_skip:
   484   assumes "crel (quicksort a l r) h h' rs"
   484   assumes "effect (quicksort a l r) h h' rs"
   485   shows "r \<le> l \<longrightarrow> h = h'"
   485   shows "r \<le> l \<longrightarrow> h = h'"
   486   using assms
   486   using assms
   487   unfolding quicksort.simps [of a l r]
   487   unfolding quicksort.simps [of a l r]
   488   by (elim crel_ifE crel_returnE) auto
   488   by (elim effect_ifE effect_returnE) auto
   489  
   489  
   490 lemma quicksort_sorts:
   490 lemma quicksort_sorts:
   491   assumes "crel (quicksort a l r) h h' rs"
   491   assumes "effect (quicksort a l r) h h' rs"
   492   assumes l_r_length: "l < Array.length h a" "r < Array.length h a" 
   492   assumes l_r_length: "l < Array.length h a" "r < Array.length h a" 
   493   shows "sorted (subarray l (r + 1) a h')"
   493   shows "sorted (subarray l (r + 1) a h')"
   494   using assms
   494   using assms
   495 proof (induct a l r arbitrary: h h' rs rule: quicksort.induct)
   495 proof (induct a l r arbitrary: h h' rs rule: quicksort.induct)
   496   case (1 a l r h h' rs)
   496   case (1 a l r h h' rs)
   497   note cr = `crel (quicksort a l r) h h' rs`
   497   note cr = `effect (quicksort a l r) h h' rs`
   498   thus ?case
   498   thus ?case
   499   proof (cases "r > l")
   499   proof (cases "r > l")
   500     case False
   500     case False
   501     hence "l \<ge> r + 1 \<or> l = r" by arith 
   501     hence "l \<ge> r + 1 \<or> l = r" by arith 
   502     with length_remains[OF cr] 1(5) show ?thesis
   502     with length_remains[OF cr] 1(5) show ?thesis
   503       by (auto simp add: subarray_Nil subarray_single)
   503       by (auto simp add: subarray_Nil subarray_single)
   504   next
   504   next
   505     case True
   505     case True
   506     { 
   506     { 
   507       fix h1 h2 p
   507       fix h1 h2 p
   508       assume part: "crel (partition a l r) h h1 p"
   508       assume part: "effect (partition a l r) h h1 p"
   509       assume qs1: "crel (quicksort a l (p - 1)) h1 h2 ()"
   509       assume qs1: "effect (quicksort a l (p - 1)) h1 h2 ()"
   510       assume qs2: "crel (quicksort a (p + 1) r) h2 h' ()"
   510       assume qs2: "effect (quicksort a (p + 1) r) h2 h' ()"
   511       from partition_returns_index_in_bounds [OF part True]
   511       from partition_returns_index_in_bounds [OF part True]
   512       have pivot: "l\<le> p \<and> p \<le> r" .
   512       have pivot: "l\<le> p \<and> p \<le> r" .
   513      note length_remains = length_remains[OF qs2] length_remains[OF qs1] partition_length_remains[OF part]
   513      note length_remains = length_remains[OF qs2] length_remains[OF qs1] partition_length_remains[OF part]
   514       from quicksort_outer_remains [OF qs2] quicksort_outer_remains [OF qs1] pivot quicksort_is_skip[OF qs1]
   514       from quicksort_outer_remains [OF qs2] quicksort_outer_remains [OF qs1] pivot quicksort_is_skip[OF qs1]
   515       have pivot_unchanged: "Array.get h1 a ! p = Array.get h' a ! p" by (cases p, auto)
   515       have pivot_unchanged: "Array.get h1 a ! p = Array.get h' a ! p" by (cases p, auto)
   555         apply (auto simp add: sorted_append sorted_Cons all_in_set_sublist'_conv)
   555         apply (auto simp add: sorted_append sorted_Cons all_in_set_sublist'_conv)
   556         by (auto simp add: set_sublist' dest: le_trans [of _ "Array.get h' a ! p"])
   556         by (auto simp add: set_sublist' dest: le_trans [of _ "Array.get h' a ! p"])
   557     }
   557     }
   558     with True cr show ?thesis
   558     with True cr show ?thesis
   559       unfolding quicksort.simps [of a l r]
   559       unfolding quicksort.simps [of a l r]
   560       by (elim crel_ifE crel_returnE crel_bindE crel_assertE) auto
   560       by (elim effect_ifE effect_returnE effect_bindE effect_assertE) auto
   561   qed
   561   qed
   562 qed
   562 qed
   563 
   563 
   564 
   564 
   565 lemma quicksort_is_sort:
   565 lemma quicksort_is_sort:
   566   assumes crel: "crel (quicksort a 0 (Array.length h a - 1)) h h' rs"
   566   assumes effect: "effect (quicksort a 0 (Array.length h a - 1)) h h' rs"
   567   shows "Array.get h' a = sort (Array.get h a)"
   567   shows "Array.get h' a = sort (Array.get h a)"
   568 proof (cases "Array.get h a = []")
   568 proof (cases "Array.get h a = []")
   569   case True
   569   case True
   570   with quicksort_is_skip[OF crel] show ?thesis
   570   with quicksort_is_skip[OF effect] show ?thesis
   571   unfolding Array.length_def by simp
   571   unfolding Array.length_def by simp
   572 next
   572 next
   573   case False
   573   case False
   574   from quicksort_sorts [OF crel] False have "sorted (sublist' 0 (List.length (Array.get h a)) (Array.get h' a))"
   574   from quicksort_sorts [OF effect] False have "sorted (sublist' 0 (List.length (Array.get h a)) (Array.get h' a))"
   575     unfolding Array.length_def subarray_def by auto
   575     unfolding Array.length_def subarray_def by auto
   576   with length_remains[OF crel] have "sorted (Array.get h' a)"
   576   with length_remains[OF effect] have "sorted (Array.get h' a)"
   577     unfolding Array.length_def by simp
   577     unfolding Array.length_def by simp
   578   with quicksort_permutes [OF crel] properties_for_sort show ?thesis by fastsimp
   578   with quicksort_permutes [OF effect] properties_for_sort show ?thesis by fastsimp
   579 qed
   579 qed
   580 
   580 
   581 subsection {* No Errors in quicksort *}
   581 subsection {* No Errors in quicksort *}
   582 text {* We have proved that quicksort sorts (if no exceptions occur).
   582 text {* We have proved that quicksort sorts (if no exceptions occur).
   583 We will now show that exceptions do not occur. *}
   583 We will now show that exceptions do not occur. *}
   588   using assms
   588   using assms
   589 proof (induct a l r p arbitrary: h rule: part1.induct)
   589 proof (induct a l r p arbitrary: h rule: part1.induct)
   590   case (1 a l r p)
   590   case (1 a l r p)
   591   thus ?case unfolding part1.simps [of a l r]
   591   thus ?case unfolding part1.simps [of a l r]
   592   apply (auto intro!: success_intros del: success_ifI simp add: not_le)
   592   apply (auto intro!: success_intros del: success_ifI simp add: not_le)
   593   apply (auto intro!: crel_intros crel_swapI)
   593   apply (auto intro!: effect_intros effect_swapI)
   594   done
   594   done
   595 qed
   595 qed
   596 
   596 
   597 lemma success_bindI' [success_intros]: (*FIXME move*)
   597 lemma success_bindI' [success_intros]: (*FIXME move*)
   598   assumes "success f h"
   598   assumes "success f h"
   599   assumes "\<And>h' r. crel f h h' r \<Longrightarrow> success (g r) h'"
   599   assumes "\<And>h' r. effect f h h' r \<Longrightarrow> success (g r) h'"
   600   shows "success (f \<guillemotright>= g) h"
   600   shows "success (f \<guillemotright>= g) h"
   601 using assms(1) proof (rule success_crelE)
   601 using assms(1) proof (rule success_effectE)
   602   fix h' r
   602   fix h' r
   603   assume "crel f h h' r"
   603   assume "effect f h h' r"
   604   moreover with assms(2) have "success (g r) h'" .
   604   moreover with assms(2) have "success (g r) h'" .
   605   ultimately show "success (f \<guillemotright>= g) h" by (rule success_bind_crelI)
   605   ultimately show "success (f \<guillemotright>= g) h" by (rule success_bind_effectI)
   606 qed
   606 qed
   607 
   607 
   608 lemma success_partitionI:
   608 lemma success_partitionI:
   609   assumes "l < r" "l < Array.length h a" "r < Array.length h a"
   609   assumes "l < r" "l < Array.length h a" "r < Array.length h a"
   610   shows "success (partition a l r) h"
   610   shows "success (partition a l r) h"
   611 using assms unfolding partition.simps swap_def
   611 using assms unfolding partition.simps swap_def
   612 apply (auto intro!: success_bindI' success_ifI success_returnI success_nthI success_updI success_part1I elim!: crel_bindE crel_updE crel_nthE crel_returnE simp add:)
   612 apply (auto intro!: success_bindI' success_ifI success_returnI success_nthI success_updI success_part1I elim!: effect_bindE effect_updE effect_nthE effect_returnE simp add:)
   613 apply (frule part_length_remains)
   613 apply (frule part_length_remains)
   614 apply (frule part_returns_index_in_bounds)
   614 apply (frule part_returns_index_in_bounds)
   615 apply auto
   615 apply auto
   616 apply (frule part_length_remains)
   616 apply (frule part_length_remains)
   617 apply (frule part_returns_index_in_bounds)
   617 apply (frule part_returns_index_in_bounds)
   631     apply (auto intro!: success_ifI success_bindI' success_returnI success_nthI success_updI success_assertI success_partitionI)
   631     apply (auto intro!: success_ifI success_bindI' success_returnI success_nthI success_updI success_assertI success_partitionI)
   632     apply (frule partition_returns_index_in_bounds)
   632     apply (frule partition_returns_index_in_bounds)
   633     apply auto
   633     apply auto
   634     apply (frule partition_returns_index_in_bounds)
   634     apply (frule partition_returns_index_in_bounds)
   635     apply auto
   635     apply auto
   636     apply (auto elim!: crel_assertE dest!: partition_length_remains length_remains)
   636     apply (auto elim!: effect_assertE dest!: partition_length_remains length_remains)
   637     apply (subgoal_tac "Suc r \<le> ri \<or> r = ri") 
   637     apply (subgoal_tac "Suc r \<le> ri \<or> r = ri") 
   638     apply (erule disjE)
   638     apply (erule disjE)
   639     apply auto
   639     apply auto
   640     unfolding quicksort.simps [of a "Suc ri" ri]
   640     unfolding quicksort.simps [of a "Suc ri" ri]
   641     apply (auto intro!: success_ifI success_returnI)
   641     apply (auto intro!: success_ifI success_returnI)