@@ -105,7 +105,7 @@ module {:options "-functionSyntax:4"} OptimizedMergeSort {
105
105
requires Relations. TotalOrdering (lessThanOrEq)
106
106
requires lo < hi <= left. Length
107
107
requires hi <= right. Length && left != right
108
- // reads left, right
108
+ reads left, right
109
109
modifies left, right
110
110
ensures ! where . Either? ==> where == resultPlacement
111
111
@@ -217,6 +217,7 @@ module {:options "-functionSyntax:4"} OptimizedMergeSort {
217
217
requires Relations. SortedBy (left[mid..hi], lessThanOrEq)
218
218
// reads left, right
219
219
modifies right
220
+ reads left, right
220
221
// We do not modify anything before lo
221
222
ensures right[.. lo] == old (right[.. lo]) && left[.. lo] == old (left[.. lo])
222
223
// We do not modify anything above hi
@@ -239,8 +240,10 @@ module {:options "-functionSyntax:4"} OptimizedMergeSort {
239
240
invariant Below (right[lo..iter], left[leftPosition..mid], lessThanOrEq)
240
241
invariant Below (right[lo..iter], left[rightPosition..hi], lessThanOrEq)
241
242
invariant Relations. SortedBy (right[lo..iter], lessThanOrEq)
242
- invariant multiset (right[lo..iter]) == multiset (left[lo..leftPosition]) + multiset ( left[mid..rightPosition])
243
+ invariant multiset (right[lo..iter]) == multiset (left[lo..leftPosition] + left[mid..rightPosition])
243
244
{
245
+
246
+ ghost var oldRightPosition, oldIter, oldLeftPosition := rightPosition, iter, leftPosition;
244
247
if leftPosition == mid || (rightPosition < hi && lessThanOrEq (left[rightPosition], left[leftPosition])) {
245
248
right[iter] := left[rightPosition];
246
249
@@ -255,7 +258,26 @@ module {:options "-functionSyntax:4"} OptimizedMergeSort {
255
258
PushStillSortedBy (right, lo, iter, lessThanOrEq);
256
259
leftPosition, iter := leftPosition + 1, iter + 1;
257
260
261
+ assert 0 < |right[lo.. iter]| && 0 < |left[leftPosition.. mid]| ==> lessThanOrEq (right[lo..iter][|right[lo..iter]| - 1], left[leftPosition..mid][0]) by {
262
+ if 0 == |right[lo.. iter]| || 0 == |left[leftPosition.. mid]| {
263
+ } else {
264
+ assert rightPosition == oldRightPosition;
265
+ assert oldLeftPosition < mid;
266
+ // This is true, but uncommenting it causes the proof to fail
267
+ // leaving it here it make what is going on a little more clear
268
+ // assert right[lo..iter][|right[lo..iter]| - 1] == right[oldIter];
269
+ assert left[leftPosition.. mid][0] == left[leftPosition];
270
+ }
271
+ }
258
272
BelowIsTransitive (right[lo..iter], left[leftPosition..mid], lessThanOrEq);
273
+
274
+ assert 0 < |right[lo.. iter]| && 0 < |left[rightPosition.. hi]| ==> lessThanOrEq (right[lo..iter][|right[lo..iter]| - 1], left[rightPosition..hi][0]) by {
275
+ if 0 == |right[lo.. iter]| || 0 == |left[rightPosition.. hi]| {
276
+ } else {
277
+ assert right[lo.. iter][|right[lo.. iter]| - 1] == right[iter - 1];
278
+ assert left[rightPosition.. hi][0] == left[rightPosition];
279
+ }
280
+ }
259
281
BelowIsTransitive (right[lo..iter], left[rightPosition..hi], lessThanOrEq);
260
282
}
261
283
}
@@ -362,7 +384,7 @@ module {:options "-functionSyntax:4"} OptimizedMergeSort {
362
384
&& right. Length < UINT64_LIMIT
363
385
requires lo < hi <= left. Length as uint64
364
386
requires hi <= right. Length as uint64 && left != right
365
- // reads left, right
387
+ reads left, right
366
388
modifies left, right
367
389
ensures ! where . Either? ==> where == resultPlacement
368
390
@@ -485,7 +507,7 @@ module {:options "-functionSyntax:4"} OptimizedMergeSort {
485
507
requires Relations. SortedBy (left[lo..mid], lessThanOrEq)
486
508
// We store "right" in [mid..hi]
487
509
requires Relations. SortedBy (left[mid..hi], lessThanOrEq)
488
- // reads left, right
510
+ reads left, right
489
511
modifies right
490
512
// We do not modify anything before lo
491
513
ensures right[.. lo] == old (right[.. lo]) && left[.. lo] == old (left[.. lo])
@@ -509,9 +531,10 @@ module {:options "-functionSyntax:4"} OptimizedMergeSort {
509
531
invariant Below (right[lo..iter], left[leftPosition..mid], lessThanOrEq)
510
532
invariant Below (right[lo..iter], left[rightPosition..hi], lessThanOrEq)
511
533
invariant Relations. SortedBy (right[lo..iter], lessThanOrEq)
512
- invariant multiset (right[lo..iter]) == multiset (left[lo..leftPosition]) + multiset ( left[mid..rightPosition])
534
+ invariant multiset (right[lo..iter]) == multiset (left[lo..leftPosition] + left[mid..rightPosition])
513
535
{
514
- label BEFORE_WORK:
536
+
537
+ ghost var oldRightPosition, oldIter, oldLeftPosition := rightPosition, iter, leftPosition;
515
538
if leftPosition == mid || (rightPosition < hi && lessThanOrEq (left[rightPosition], left[leftPosition])) {
516
539
right[iter] := left[rightPosition];
517
540
@@ -529,11 +552,10 @@ module {:options "-functionSyntax:4"} OptimizedMergeSort {
529
552
leftPosition, iter := leftPosition + 1, iter + 1;
530
553
531
554
assert 0 < |right[lo.. iter]| && 0 < |left[leftPosition.. mid]| ==> lessThanOrEq (right[lo..iter][|right[lo..iter]| - 1], left[leftPosition..mid][0]) by {
532
- if 0 < |right[lo.. iter]| && 0 < |left[leftPosition.. mid]| {
533
- assert lessThanOrEq (left[leftPosition-1], left[leftPosition]) by {
534
- assert lo <= leftPosition- 1 < leftPosition < mid;
535
- assert Relations. SortedBy (left[lo..mid], lessThanOrEq);
536
- }
555
+ if 0 == |right[lo.. iter]| || 0 == |left[leftPosition.. mid]| {
556
+ } else {
557
+ assert right[lo.. iter][|right[lo.. iter]| - 1] == right[iter - 1];
558
+ assert left[leftPosition.. mid][0] == left[leftPosition];
537
559
}
538
560
}
539
561
BelowIsTransitive (right[lo..iter], left[leftPosition..mid], lessThanOrEq);
0 commit comments