This repository has been archived on 2023-06-18. You can view files and clone it, but cannot push or open issues or pull requests.
soft-an01/slowsort.dfy

78 lines
2.3 KiB
Plaintext

predicate sorted(s: seq<int>) {
forall i,j: int :: 0 <= i < j < |s| ==> s[i] <= s[j]
}
predicate sameElements(sa: seq<int>, sb: seq<int>) {
multiset(sa) == multiset(sb)
}
lemma SubSort(s: seq<int>, i: int, j: int)
requires sorted(s)
requires 0 <= i < j <= |s|
ensures sorted(s[i..j])
{
}
method SlowSortHelper(a: array<int>, startIdx: int, endIdx: int)
requires 0 <= startIdx <= endIdx < a.Length
modifies a
ensures a[..startIdx] == old(a[..startIdx])
ensures endIdx < a.Length ==> a[endIdx + 1..] == old(a[endIdx + 1..])
ensures sorted(a[startIdx..endIdx + 1])
ensures multiset(a[startIdx..endIdx + 1]) == multiset(old(a[startIdx..endIdx + 1]))
decreases endIdx - startIdx
{
if (endIdx == startIdx) {
return;
}
var middleIdx: int := (startIdx + endIdx) / 2;
assert sameElements(a[startIdx..endIdx + 1], old(a[startIdx..endIdx + 1]));
SlowSortHelper(a, startIdx, middleIdx);
SlowSortHelper(a, middleIdx + 1, endIdx);
assert 0 <= startIdx <= middleIdx < endIdx;
assert a[..startIdx] == old(a[..startIdx]);
assert endIdx < a.Length ==> a[endIdx + 1..] == old(a[endIdx + 1..]);
assert sorted(a[startIdx..middleIdx + 1]);
assert sorted(a[middleIdx + 1..endIdx + 1]);
if (a[endIdx] < a[middleIdx]) {
a[endIdx], a[middleIdx] := a[middleIdx], a[endIdx];
}
assert a[middleIdx] <= a[endIdx];
assert forall j: int :: startIdx <= j <= endIdx ==> a[j] <= a[endIdx];
SlowSortHelper(a, startIdx, endIdx - 1);
assert 0 <= startIdx <= middleIdx < endIdx;
assert sorted(a[startIdx..endIdx]);
assert multiset(a[startIdx..endIdx]) == multiset(old(a[startIdx..endIdx]));
assert forall j: int :: startIdx <= j <= endIdx ==> old(a[j]) <= a[endIdx];
// assert 0 <= startIdx < middleIdx + 1 <= endIdx;
// assert sorted(a[startIdx..endIdx]);
// assert a[..startIdx] == old(a[..startIdx]);
// assert endIdx < a.Length ==> a[endIdx + 1..] == old(a[endIdx + 1..]);
// assert sorted(a[startIdx..endIdx]);
// assert middleIdx <= endIdx ==> a[middleIdx] < a[endIdx];
// assert forall j: int :: startIdx <= j < endIdx ==> a[j] <= a[endIdx];
}
method SlowSort(a: array<int>)
modifies a
ensures sorted(a[..])
ensures sameElements(a[..], old(a[..]))
{
if (a.Length > 1) {
SlowSortHelper(a, 0, a.Length - 1);
}
}