Repository navigation
Expand file tree
/
Copy pathlist.mlw
More file actions
693 lines (482 loc) · 15.3 KB
/
Copy pathlist.mlw
File metadata and controls
693 lines (482 loc) · 15.3 KB
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
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
(** {1 Polymorphic Lists} *)
(** {2 Basic theory of polymorphic lists} *)
module List
type list 'a = Nil | Cons 'a (list 'a)
let predicate is_nil (l:list 'a)
ensures { result <-> l = Nil }
=
match l with Nil -> true | Cons _ _ -> false end
end
(** {2 Length of a list} *)
module Length
use int.Int
use List
let rec function length (l: list 'a) : int =
match l with
| Nil -> 0
| Cons _ r -> 1 + length r
end
lemma Length_nonnegative: forall l: list 'a. length l >= 0
meta "remove_unused:dependency" lemma Length_nonnegative, function length
lemma Length_nil: forall l: list 'a. length l = 0 <-> l = Nil
meta "remove_unused:dependency" lemma Length_nil, function length
end
(** {2 Membership in a list} *)
module Mem
use List
predicate mem (x: 'a) (l: list 'a) = match l with
| Nil -> false
| Cons y r -> x = y \/ mem x r
end
end
(** {2 Quantifiers on lists} *)
module Quant
use List
use Mem
let rec function for_all (p: 'a -> bool) (l:list 'a) : bool
ensures { result <-> forall x. mem x l -> p x }
=
match l with
| Nil -> true
| Cons x r -> p x && for_all p r
end
let rec function for_some (p: 'a -> bool) (l:list 'a) : bool
ensures { result <-> exists x. mem x l /\ p x }
=
match l with
| Nil -> false
| Cons x r -> p x || for_some p r
end
let function mem (eq:'a -> 'a -> bool) (x:'a) (l:list 'a) : bool
ensures { result <-> exists y. mem y l /\ eq x y }
=
for_some (eq x) l
end
module Elements
use set.Fset
use List
use Mem
function elements (l: list 'a) : fset 'a =
match l with
| Nil -> empty
| Cons x r -> add x (elements r)
end
lemma elements_mem:
forall x: 'a, l: list 'a. mem x l <-> Fset.mem x (elements l)
end
(** {2 Nth element of a list} *)
module Nth
use List
use option.Option
use int.Int
let rec function nth (n: int) (l: list 'a) : option 'a =
match l with
| Nil -> None
| Cons x r -> if n = 0 then Some x else nth (n - 1) r
end
end
module NthNoOpt
use List
use int.Int
function nth (n: int) (l: list 'a) : 'a
axiom nth_cons_0: forall x:'a, r:list 'a. nth 0 (Cons x r) = x
meta "remove_unused:dependency" axiom nth_cons_0, function nth
axiom nth_cons_n: forall x:'a, r:list 'a, n:int.
n > 0 -> nth n (Cons x r) = nth (n-1) r
meta "remove_unused:dependency" axiom nth_cons_n, function nth
end
module NthLength
use int.Int
use option.Option
use List
use export Nth
use export Length
lemma nth_none_1:
forall l: list 'a, i: int. i < 0 -> nth i l = None
meta "remove_unused:dependency" lemma nth_none_1, function nth
lemma nth_none_2:
forall l: list 'a, i: int. i >= length l -> nth i l = None
meta "remove_unused:dependency" lemma nth_none_2, function nth
lemma nth_none_3:
forall l: list 'a, i: int. nth i l = None -> i < 0 \/ i >= length l
meta "remove_unused:dependency" lemma nth_none_3, function nth
end
(** {2 Head and tail} *)
module HdTl
use List
use option.Option
let function hd (l: list 'a) : option 'a = match l with
| Nil -> None
| Cons h _ -> Some h
end
let function tl (l: list 'a) : option (list 'a) = match l with
| Nil -> None
| Cons _ t -> Some t
end
end
module HdTlNoOpt
use List
function hd (l: list 'a) : 'a
axiom hd_cons: forall x:'a, r:list 'a. hd (Cons x r) = x
meta "remove_unused:dependency" axiom hd_cons, function hd
function tl (l: list 'a) : list 'a
axiom tl_cons: forall x:'a, r:list 'a. tl (Cons x r) = r
meta "remove_unused:dependency" axiom tl_cons, function tl
end
(** {2 Relation between head, tail, and nth} *)
module NthHdTl
use int.Int
use option.Option
use List
use Nth
use HdTl
lemma Nth_tl:
forall l1 l2: list 'a. tl l1 = Some l2 ->
forall i: int. i <> -1 -> nth i l2 = nth (i+1) l1
meta "remove_unused:dependency" lemma Nth_tl, function nth
lemma Nth0_head:
forall l: list 'a. nth 0 l = hd l
meta "remove_unused:dependency" lemma Nth0_head, function nth
end
(** {2 Appending two lists} *)
module Append
use List
let rec function (++) (l1 l2: list 'a) : list 'a =
match l1 with
| Nil -> l2
| Cons x1 r1 -> Cons x1 (r1 ++ l2)
end
lemma Append_assoc:
forall l1 [@induction] l2 l3: list 'a.
l1 ++ (l2 ++ l3) = (l1 ++ l2) ++ l3
meta "remove_unused:dependency" lemma Append_assoc, function (++)
lemma Append_l_nil:
forall l: list 'a. l ++ Nil = l
meta "remove_unused:dependency" lemma Append_l_nil, function (++)
use Length
use int.Int
lemma Append_length:
forall l1 [@induction] l2: list 'a. length (l1 ++ l2) = length l1 + length l2
meta "remove_unused:dependency" lemma Append_length, function (++)
use Mem
lemma mem_append:
forall x: 'a, l1 [@induction] l2: list 'a.
mem x (l1 ++ l2) <-> mem x l1 \/ mem x l2
meta "remove_unused:dependency" lemma mem_append, function (++)
lemma mem_decomp:
forall x: 'a, l: list 'a.
mem x l -> exists l1 l2: list 'a. l = l1 ++ Cons x l2
meta "remove_unused:dependency" lemma mem_decomp, function (++)
end
module NthLengthAppend
use int.Int
use List
use export NthLength
use export Append
lemma nth_append_1:
forall l1 l2: list 'a, i: int.
i < length l1 -> nth i (l1 ++ l2) = nth i l1
meta "remove_unused:dependency" lemma nth_append_1, function nth
lemma nth_append_2:
forall l1 [@induction] l2: list 'a, i: int.
length l1 <= i -> nth i (l1 ++ l2) = nth (i - length l1) l2
meta "remove_unused:dependency" lemma nth_append_2, function nth
end
(** {2 Reversing a list} *)
module Reverse
use List
use Append
let rec function reverse (l: list 'a) : list 'a =
match l with
| Nil -> Nil
| Cons x r -> reverse r ++ Cons x Nil
end
lemma reverse_append:
forall l1 l2: list 'a, x: 'a.
(reverse (Cons x l1)) ++ l2 = (reverse l1) ++ (Cons x l2)
meta "remove_unused:dependency" lemma reverse_append, function reverse
lemma reverse_cons:
forall l: list 'a, x: 'a.
reverse (Cons x l) = reverse l ++ Cons x Nil
meta "remove_unused:dependency" lemma reverse_cons, function reverse
lemma cons_reverse:
forall l: list 'a, x: 'a.
Cons x (reverse l) = reverse (l ++ Cons x Nil)
meta "remove_unused:dependency" lemma cons_reverse, function reverse
lemma reverse_reverse:
forall l: list 'a. reverse (reverse l) = l
meta "remove_unused:dependency" lemma reverse_reverse, function reverse
use Mem
lemma reverse_mem:
forall l: list 'a, x: 'a. mem x l <-> mem x (reverse l)
meta "remove_unused:dependency" lemma reverse_mem, function reverse
use Length
lemma Reverse_length:
forall l: list 'a. length (reverse l) = length l
meta "remove_unused:dependency" lemma Reverse_length, function reverse
end
(** {2 Reverse append} *)
module RevAppend
use List
let rec function rev_append (s t: list 'a) : list 'a =
match s with
| Cons x r -> rev_append r (Cons x t)
| Nil -> t
end
use Append
lemma rev_append_append_l:
forall r [@induction] s t: list 'a.
rev_append (r ++ s) t = rev_append s (rev_append r t)
meta "remove_unused:dependency" lemma rev_append_append_l, function rev_append
use int.Int
use Length
lemma rev_append_length:
forall s [@induction] t: list 'a.
length (rev_append s t) = length s + length t
meta "remove_unused:dependency" lemma rev_append_length, function rev_append
use Reverse
lemma rev_append_def:
forall r [@induction] s: list 'a. rev_append r s = reverse r ++ s
meta "remove_unused:dependency" lemma rev_append_def, function rev_append
lemma rev_append_append_r:
forall r s t: list 'a.
rev_append r (s ++ t) = rev_append (rev_append s r) t
meta "remove_unused:dependency" lemma rev_append_append_r, function rev_append
end
(** {2 Zip} *)
module Combine
use List
let rec function combine (x: list 'a) (y: list 'b) : list ('a, 'b)
= match x, y with
| Cons x0 x, Cons y0 y -> Cons (x0, y0) (combine x y)
| _ -> Nil
end
end
(** {2 Sorted lists for some order as parameter} *)
module Sorted
use List
type t
predicate le t t
clone relations.Transitive with
type t = t, predicate rel = le, axiom Trans
inductive sorted (l: list t) =
| Sorted_Nil:
sorted Nil
| Sorted_One:
forall x: t. sorted (Cons x Nil)
| Sorted_Two:
forall x y: t, l: list t.
le x y -> sorted (Cons y l) -> sorted (Cons x (Cons y l))
use Mem
lemma sorted_mem:
forall x: t, l: list t.
(forall y: t. mem y l -> le x y) /\ sorted l <-> sorted (Cons x l)
meta "remove_unused:dependency" lemma sorted_mem, predicate sorted
use Append
lemma sorted_append:
forall l1 [@induction] l2: list t.
(sorted l1 /\ sorted l2 /\ (forall x y: t. mem x l1 -> mem y l2 -> le x y))
<->
sorted (l1 ++ l2)
meta "remove_unused:dependency" lemma sorted_append, predicate sorted
end
(** {2 Sorted lists of integers} *)
module SortedInt
use int.Int
clone export Sorted with type t = int, predicate le = (<=), goal Transitive.Trans
end
module RevSorted
type t
predicate le t t
clone relations.Transitive with
type t = t, predicate rel = le, axiom Trans
predicate ge (x y: t) = le y x
use List
clone Sorted as Incr with type t = t, predicate le = le, goal .
clone Sorted as Decr with type t = t, predicate le = ge, goal .
predicate compat (s t: list t) =
match s, t with
| Cons x _, Cons y _ -> le x y
| _, _ -> true
end
use RevAppend
lemma rev_append_sorted_incr:
forall s [@induction] t: list t.
Incr.sorted (rev_append s t) <->
Decr.sorted s /\ Incr.sorted t /\ compat s t
lemma rev_append_sorted_decr:
forall s [@induction] t: list t.
Decr.sorted (rev_append s t) <->
Incr.sorted s /\ Decr.sorted t /\ compat t s
end
(** {2 Number of occurrences in a list} *)
module NumOcc
use int.Int
use List
function num_occ (x: 'a) (l: list 'a) : int =
match l with
| Nil -> 0
| Cons y r -> (if x = y then 1 else 0) + num_occ x r
end
(** number of occurrences of `x` in `l` *)
lemma Num_Occ_NonNeg: forall x:'a, l: list 'a. num_occ x l >= 0
meta "remove_unused:dependency" lemma Num_Occ_NonNeg, function num_occ
use Mem
lemma Mem_Num_Occ :
forall x: 'a, l: list 'a. mem x l <-> num_occ x l > 0
meta "remove_unused:dependency" lemma Mem_Num_Occ, function num_occ
use Append
lemma Append_Num_Occ :
forall x: 'a, l1 [@induction] l2: list 'a.
num_occ x (l1 ++ l2) = num_occ x l1 + num_occ x l2
meta "remove_unused:dependency" lemma Append_Num_Occ, function num_occ
use Reverse
lemma reverse_num_occ :
forall x: 'a, l: list 'a.
num_occ x l = num_occ x (reverse l)
meta "remove_unused:dependency" lemma reverse_num_occ, function num_occ
end
(** {2 Permutation of lists} *)
module Permut
use NumOcc
use List
predicate permut (l1: list 'a) (l2: list 'a) =
forall x: 'a. num_occ x l1 = num_occ x l2
lemma Permut_refl: forall l: list 'a. permut l l
meta "remove_unused:dependency" lemma Permut_refl, predicate permut
lemma Permut_sym: forall l1 l2: list 'a. permut l1 l2 -> permut l2 l1
meta "remove_unused:dependency" lemma Permut_sym, predicate permut
lemma Permut_trans:
forall l1 l2 l3: list 'a. permut l1 l2 -> permut l2 l3 -> permut l1 l3
meta "remove_unused:dependency" lemma Permut_trans, predicate permut
lemma Permut_cons:
forall x: 'a, l1 l2: list 'a.
permut l1 l2 -> permut (Cons x l1) (Cons x l2)
meta "remove_unused:dependency" lemma Permut_cons, predicate permut
lemma Permut_swap:
forall x y: 'a, l: list 'a. permut (Cons x (Cons y l)) (Cons y (Cons x l))
meta "remove_unused:dependency" lemma Permut_swap, predicate permut
use Append
lemma Permut_cons_append:
forall x : 'a, l1 l2 : list 'a.
permut (Cons x l1 ++ l2) (l1 ++ Cons x l2)
meta "remove_unused:dependency" lemma Permut_cons_append, predicate permut
lemma Permut_assoc:
forall l1 l2 l3: list 'a.
permut ((l1 ++ l2) ++ l3) (l1 ++ (l2 ++ l3))
meta "remove_unused:dependency" lemma Permut_assoc, predicate permut
lemma Permut_append:
forall l1 l2 k1 k2 : list 'a.
permut l1 k1 -> permut l2 k2 -> permut (l1 ++ l2) (k1 ++ k2)
meta "remove_unused:dependency" lemma Permut_append, predicate permut
lemma Permut_append_swap:
forall l1 l2 : list 'a.
permut (l1 ++ l2) (l2 ++ l1)
meta "remove_unused:dependency" lemma Permut_append_swap, predicate permut
use Mem
lemma Permut_mem:
forall x: 'a, l1 l2: list 'a. permut l1 l2 -> mem x l1 -> mem x l2
meta "remove_unused:dependency" lemma Permut_mem, predicate permut
use Length
lemma Permut_length:
forall l1 [@induction] l2: list 'a. permut l1 l2 -> length l1 = length l2
meta "remove_unused:dependency" lemma Permut_length, predicate permut
end
(** {2 List with pairwise distinct elements} *)
module Distinct
use List
use Mem
predicate distinct (l: list 'a) =
match l with
| Nil | Cons _ Nil -> true
| Cons x xs -> not (mem x xs) /\ distinct xs
end
use Append
lemma distinct_append:
forall l1 [@induction] l2: list 'a.
distinct l1 -> distinct l2 -> (forall x:'a. mem x l1 -> not (mem x l2)) ->
distinct (l1 ++ l2)
meta "remove_unused:dependency" lemma distinct_append, predicate distinct
end
module Prefix
use List
use int.Int
let rec function prefix (n: int) (l: list 'a) : list 'a =
if n <= 0 then Nil else
match l with
| Nil -> Nil
| Cons x r -> Cons x (prefix (n-1) r)
end
end
module Sum
use List
use int.Int
let rec function sum (l: list int) : int =
match l with
| Nil -> 0
| Cons x r -> x + sum r
end
end
(*
(** {2 Induction on lists} *)
module Induction
use List
(* type elt *)
(* predicate p (list elt) *)
axiom Induction:
forall p: list 'a -> bool.
p (Nil: list 'a) ->
(forall x:'a. forall l:list 'a. p l -> p (Cons x l)) ->
forall l:list 'a. p l
end
*)
(** {2 Maps as lists of pairs} *)
module Map
use List
function map (f: 'a -> 'b) (l: list 'a) : list 'b =
match l with
| Nil -> Nil
| Cons x r -> Cons (f x) (map f r)
end
end
(** {2 Generic recursors on lists} *)
module FoldLeft
use List
function fold_left (f: 'b -> 'a -> 'b) (acc: 'b) (l: list 'a) : 'b =
match l with
| Nil -> acc
| Cons x r -> fold_left f (f acc x) r
end
use Append
lemma fold_left_append:
forall l1 [@induction] l2: list 'a, f: 'b -> 'a -> 'b, acc : 'b.
fold_left f acc (l1++l2) = fold_left f (fold_left f acc l1) l2
meta "remove_unused:dependency" lemma fold_left_append, function fold_left
end
module FoldRight
use List
function fold_right (f: 'a -> 'b -> 'b) (l: list 'a) (acc: 'b) : 'b =
match l with
| Nil -> acc
| Cons x r -> f x (fold_right f r acc)
end
use Append
lemma fold_right_append:
forall l1 [@induction] l2: list 'a, f: 'a -> 'b -> 'b, acc : 'b.
fold_right f (l1++l2) acc = fold_right f l1 (fold_right f l2 acc)
meta "remove_unused:dependency" lemma fold_right_append, function fold_right
end
(** {2 Importation of all list theories in one} *)
module ListRich
use export List
use export Length
use export Mem
use export Nth
use export HdTl
use export NthHdTl
use export Append
use export Reverse
use export RevAppend
use export NumOcc
use export Permut
end