-
Notifications
You must be signed in to change notification settings - Fork 0
/
BubbleSort.v
303 lines (261 loc) · 9.43 KB
/
BubbleSort.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
From VFA Require Import Perm.
Inductive sorted: list nat -> Prop :=
| sorted_nil:
sorted nil
| sorted_1: forall x,
sorted (x :: nil)
| sorted_cons: forall x y l,
x <= y -> sorted (y :: l) -> sorted (x :: y :: l).
Definition is_a_sorting_algorithm (f: list nat -> list nat) :=
forall al, Permutation al (f al) /\ sorted (f al).
Fixpoint bubble_pass (l: list nat): list nat :=
match l with
| [] => []
| h :: t => match (bubble_pass t) with
| [] => [h]
| h' :: t' => if h <=? h'
then h :: h' :: t'
else h' :: h :: t'
end
end.
Compute bubble_pass [1; 0; 5; 7; 4; 0; 3; 2].
Compute bubble_pass [].
Compute bubble_pass [9; 3; 2; 8; 7; 4; 5; 1; 0; 6].
Compute bubble_pass [4; 8; 0; 7; 2; 3; 1; 6; 5; 9].
Fixpoint bubble_sort' (l: list nat) (len: nat): list nat :=
match len with
| O => l
| S len' => match (bubble_pass l) with
| h :: t => h :: (bubble_sort' t len')
| _ => []
end
end.
Definition bubble_sort (l: list nat): list nat :=
bubble_sort' l (length l).
Compute bubble_sort [1; 0; 5; 7; 4; 0; 3; 2].
Compute bubble_sort [].
Compute bubble_sort [9; 3; 2; 8; 7; 4; 5; 1; 0; 6].
Compute bubble_sort [4; 8; 0; 7; 2; 3; 1; 6; 5; 9].
Lemma bubble_pass_perm: forall l,
Permutation l (bubble_pass l).
Proof.
intro l. induction l as [| h t IHl'].
- simpl. Search (Permutation [] []). apply perm_nil.
- simpl. destruct (bubble_pass t) as [| h' t'] eqn:Ebpt.
+ Search (Permutation [] _). Search Permutation.
apply Permutation_sym in IHl'. apply Permutation_nil in IHl'.
subst. apply Permutation_refl.
+ bdestruct (h <=? h').
* apply perm_skip. apply IHl'.
* rewrite perm_swap. apply perm_skip. apply IHl'.
Qed.
Lemma bubble_sort_nil: forall l n,
bubble_sort' l n = [] -> l = [].
Proof.
intros l n H. destruct l as [| h t] eqn:El.
- reflexivity.
- destruct n as [| n'] eqn:En.
+ simpl in H. inversion H.
+ simpl in H. destruct (bubble_pass t) as [| h' t'] eqn:Ebpt.
* inversion H.
* bdestruct (h <=? h');
inversion H.
Qed.
Lemma bubble_sort_perm': forall l n,
length l = n -> Permutation l (bubble_sort' l n).
Proof.
intros l n. generalize dependent l.
induction n as [| n']; intros l H.
- simpl. apply Permutation_refl.
- destruct l as [| h t] eqn:El; subst.
+ inversion H.
+ simpl. assert (HP := bubble_pass_perm t).
destruct (bubble_pass t) as [| h1 t1] eqn:Ebpt.
* apply perm_skip. Search (Permutation [] _ -> _ = _).
apply Permutation_sym in HP. apply Permutation_nil in HP.
subst. inversion H. simpl. apply perm_nil.
* bdestruct (h <=? h1).
{ apply perm_skip. apply Permutation_trans with (l' := h1 :: t1).
- apply HP.
- apply IHn'. inversion H. subst.
Search (Permutation _ _ -> length _ = length _).
apply Permutation_length. apply Permutation_sym. apply HP. }
{ destruct (bubble_sort' (h :: t1) n') as [| h2 t2] eqn:Ebs.
- apply bubble_sort_nil in Ebs. inversion Ebs.
- apply Permutation_trans with (l' := h :: h1 :: t1).
+ apply perm_skip. apply HP.
+ rewrite perm_swap. apply perm_skip.
rewrite <- Ebs. apply IHn'.
inversion H. subst.
apply Permutation_length in HP. rewrite HP.
simpl. reflexivity. }
Qed.
Theorem bubble_sort_perm: forall l,
Permutation l (bubble_sort l).
Proof.
intro l. unfold bubble_sort.
apply bubble_sort_perm'. reflexivity.
Qed.
Lemma bubble_pass_nil: forall l,
bubble_pass l = [] -> l = [].
Proof.
intros l H. destruct l as [| h t] eqn:El.
- reflexivity.
- simpl in H. destruct (bubble_pass t) as [| h' t'] eqn:Ebpt.
+ inversion H.
+ bdestruct (h <=? h');
inversion H.
Qed.
Lemma bubble_pass_min: forall l l' x y,
bubble_pass l = (x :: l') ->
In y l ->
x <= y.
Proof.
intro l. induction l as [| h t IHl']; intros l' x y Hbp Hin.
- simpl in Hbp. inversion Hbp.
- simpl in Hbp. destruct (bubble_pass t) as [| h1 t1] eqn:Ebpt.
+ inversion Hbp. subst. clear Hbp.
destruct Hin as [H | H].
* omega.
* apply bubble_pass_nil in Ebpt. subst. inversion H.
+ bdestruct (h <=? h1).
* inversion Hbp. subst. clear Hbp.
destruct Hin as [H' | H'].
{ omega. }
{ Check le_trans. apply le_trans with (m := h1).
- apply H.
- apply IHl' with (l' := t1).
* reflexivity.
* apply H'. }
* inversion Hbp. subst. clear Hbp.
destruct Hin as [H' | H'].
{ omega. }
{ apply IHl' with (l' := t1).
- reflexivity.
- apply H'. }
Qed.
Lemma bubble_pass_sorted: forall l l' x,
bubble_pass l = (x :: l') ->
sorted (bubble_sort' l' (length l')) ->
sorted (x :: bubble_sort' l' (length l')).
Proof.
intros l l' x Hbp Hs.
destruct l' as [| h' t'] eqn:El'.
- simpl. apply sorted_1.
- simpl in *. destruct (bubble_pass t') as [| h1 t1] eqn:Ebpt'.
+ apply bubble_pass_nil in Ebpt'. subst.
simpl in *. apply sorted_cons.
* Check bubble_pass_min. apply (bubble_pass_min l [h'] x h').
{ apply Hbp. }
{ assert (HP := bubble_pass_perm l). rewrite Hbp in HP.
Check Permutation_in. apply Permutation_in with (l := [x; h']).
- apply Permutation_sym. apply HP.
- simpl. right. left. reflexivity. }
* apply sorted_1.
+ bdestruct (h' <=? h1).
* apply sorted_cons.
{ apply (bubble_pass_min l (h' :: t') x h').
- apply Hbp.
- Check bubble_pass_perm. assert (HP := bubble_pass_perm l).
rewrite Hbp in HP. apply Permutation_in with ( l:= x :: h' :: t').
+ apply Permutation_sym. apply HP.
+ simpl. right. left. reflexivity. }
{ apply Hs. }
* apply sorted_cons.
{ Check bubble_pass_min. apply (bubble_pass_min l (h' :: t') x h1).
- apply Hbp.
- apply Permutation_in with (l := x :: h' :: t').
+ rewrite <- Hbp. apply Permutation_sym. apply bubble_pass_perm.
+ simpl. right. right.
apply Permutation_in with (l := bubble_pass t').
* apply Permutation_sym. apply bubble_pass_perm.
* rewrite Ebpt'. simpl. left. reflexivity. }
{ apply Hs. }
Qed.
Lemma bubble_pass_preserves_elems: forall l x,
In x l <-> In x (bubble_pass l).
Proof.
intros l x. split; intro H.
- apply Permutation_in with (l := l).
+ apply bubble_pass_perm.
+ apply H.
- apply Permutation_in with (l := bubble_pass l).
+ apply Permutation_sym. apply bubble_pass_perm.
+ apply H.
Qed.
Lemma bubble_sort'_sorted_aux: forall l x,
sorted (bubble_sort' l (length l)) ->
Forall (fun z => x <= z) l ->
sorted (x :: bubble_sort' l (length l)).
Proof.
intros l x Hs HF. rewrite Forall_forall in HF.
destruct l as [| h t] eqn:El.
- simpl. apply sorted_1.
- simpl in *. destruct (bubble_pass t) as [| h1 t1] eqn:Ebpt.
+ apply sorted_cons.
* apply HF. left. reflexivity.
* apply bubble_pass_nil in Ebpt. subst.
simpl. apply sorted_1.
+ bdestruct (h <=? h1).
* apply sorted_cons.
{ apply HF. left. reflexivity. }
{ apply Hs. }
* apply sorted_cons.
{ apply HF. right.
apply bubble_pass_preserves_elems. rewrite Ebpt.
left. reflexivity. }
{ apply Hs. }
Qed.
Lemma bubble_sort'_sorted: forall l n,
length l = n -> sorted (bubble_sort' l n).
Proof.
intros l n. generalize dependent l.
induction n as [| n' IHn']; intros l H.
- simpl. destruct l.
+ apply sorted_nil.
+ inversion H.
- destruct l as [| h t] eqn:El.
+ inversion H.
+ simpl. destruct (bubble_pass t) as [| h1 t1] eqn:Ebpt.
* apply bubble_pass_nil in Ebpt. subst.
inversion H. simpl. apply sorted_1.
* subst.
assert (HP := bubble_pass_perm t). apply Permutation_length in HP.
bdestruct (h <=? h1).
{ inversion H. subst. clear H.
rewrite Ebpt in HP. rewrite HP.
Check bubble_sort'_sorted_aux. apply bubble_sort'_sorted_aux.
- rewrite HP in IHn'. apply IHn'. reflexivity.
- rewrite Forall_forall. intros x Hin. Check bubble_pass_min.
apply le_trans with (m := h1).
+ apply H0.
+ apply (bubble_pass_min t t1 h1 x).
* apply Ebpt.
* apply bubble_pass_preserves_elems. rewrite Ebpt. apply Hin. }
{ inversion H. subst. clear H.
rewrite Ebpt in HP. inversion HP. subst.
assert (Hlen: length t = length (h :: t1)).
{ simpl. rewrite HP. reflexivity. }
rewrite Hlen. apply bubble_sort'_sorted_aux.
- rewrite H1 in IHn'. apply IHn'. reflexivity.
- rewrite Forall_forall. intros x Hin.
destruct Hin as [Hin | Hin].
+ omega.
+ Check bubble_pass_min. apply (bubble_pass_min t t1 h1 x).
* apply Ebpt.
* apply bubble_pass_preserves_elems.
rewrite Ebpt. right. apply Hin. }
Qed.
Theorem bubble_sort_sorted: forall l,
sorted (bubble_sort l).
Proof.
intro l. unfold bubble_sort.
apply bubble_sort'_sorted with (n := length l). reflexivity.
Qed.
Theorem bubble_sort_is_correct:
is_a_sorting_algorithm bubble_sort.
Proof.
unfold is_a_sorting_algorithm. intro l. split.
- apply bubble_sort_perm.
- apply bubble_sort_sorted.
Qed.