@@ -105,7 +105,7 @@ module {:options "-functionSyntax:4"} OptimizedMergeSort {
105105 requires Relations. TotalOrdering (lessThanOrEq)
106106 requires lo < hi <= left. Length
107107 requires hi <= right. Length && left != right
108- // reads left, right
108+ reads left, right
109109 modifies left, right
110110 ensures ! where . Either? ==> where == resultPlacement
111111
@@ -217,6 +217,7 @@ module {:options "-functionSyntax:4"} OptimizedMergeSort {
217217 requires Relations. SortedBy (left[mid..hi], lessThanOrEq)
218218 // reads left, right
219219 modifies right
220+ reads left, right
220221 // We do not modify anything before lo
221222 ensures right[.. lo] == old (right[.. lo]) && left[.. lo] == old (left[.. lo])
222223 // We do not modify anything above hi
@@ -239,8 +240,10 @@ module {:options "-functionSyntax:4"} OptimizedMergeSort {
239240 invariant Below (right[lo..iter], left[leftPosition..mid], lessThanOrEq)
240241 invariant Below (right[lo..iter], left[rightPosition..hi], lessThanOrEq)
241242 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])
243244 {
245+
246+ ghost var oldRightPosition, oldIter, oldLeftPosition := rightPosition, iter, leftPosition;
244247 if leftPosition == mid || (rightPosition < hi && lessThanOrEq (left[rightPosition], left[leftPosition])) {
245248 right[iter] := left[rightPosition];
246249
@@ -255,7 +258,26 @@ module {:options "-functionSyntax:4"} OptimizedMergeSort {
255258 PushStillSortedBy (right, lo, iter, lessThanOrEq);
256259 leftPosition, iter := leftPosition + 1, iter + 1;
257260
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+ }
258272 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+ }
259281 BelowIsTransitive (right[lo..iter], left[rightPosition..hi], lessThanOrEq);
260282 }
261283 }
@@ -362,7 +384,7 @@ module {:options "-functionSyntax:4"} OptimizedMergeSort {
362384 && right. Length < UINT64_LIMIT
363385 requires lo < hi <= left. Length as uint64
364386 requires hi <= right. Length as uint64 && left != right
365- // reads left, right
387+ reads left, right
366388 modifies left, right
367389 ensures ! where . Either? ==> where == resultPlacement
368390
@@ -485,7 +507,7 @@ module {:options "-functionSyntax:4"} OptimizedMergeSort {
485507 requires Relations. SortedBy (left[lo..mid], lessThanOrEq)
486508 // We store "right" in [mid..hi]
487509 requires Relations. SortedBy (left[mid..hi], lessThanOrEq)
488- // reads left, right
510+ reads left, right
489511 modifies right
490512 // We do not modify anything before lo
491513 ensures right[.. lo] == old (right[.. lo]) && left[.. lo] == old (left[.. lo])
@@ -509,9 +531,10 @@ module {:options "-functionSyntax:4"} OptimizedMergeSort {
509531 invariant Below (right[lo..iter], left[leftPosition..mid], lessThanOrEq)
510532 invariant Below (right[lo..iter], left[rightPosition..hi], lessThanOrEq)
511533 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])
513535 {
514- label BEFORE_WORK:
536+
537+ ghost var oldRightPosition, oldIter, oldLeftPosition := rightPosition, iter, leftPosition;
515538 if leftPosition == mid || (rightPosition < hi && lessThanOrEq (left[rightPosition], left[leftPosition])) {
516539 right[iter] := left[rightPosition];
517540
@@ -529,11 +552,10 @@ module {:options "-functionSyntax:4"} OptimizedMergeSort {
529552 leftPosition, iter := leftPosition + 1, iter + 1;
530553
531554 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];
537559 }
538560 }
539561 BelowIsTransitive (right[lo..iter], left[leftPosition..mid], lessThanOrEq);
0 commit comments