Skip to content

Commit d251afe

Browse files
committed
shorten equivalence proof
1 parent 0d969dc commit d251afe

File tree

2 files changed

+26
-44
lines changed

2 files changed

+26
-44
lines changed

src/Util/FisherYates/Equivalence.dfy

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*******************************************************************************
2+
* Copyright by the contributors to the Dafny Project
3+
* SPDX-License-Identifier: MIT
4+
*******************************************************************************/
5+
6+
module FisherYates.Equivalence {
7+
import Model
8+
import Rand
9+
10+
ghost predicate LoopInvariant<T>(prevI: nat, i: nat, a: array<T>, prevASeq: seq<T>, oldASeq: seq<T>, oldS: Rand.Bitstream, prevS: Rand.Bitstream, s: Rand.Bitstream)
11+
reads a
12+
{
13+
&& prevI <= |prevASeq|
14+
&& i <= a.Length - 1
15+
&& Model.Shuffle(oldASeq)(oldS) == Model.Shuffle(prevASeq, prevI)(prevS)
16+
&& Model.Shuffle(prevASeq, prevI)(prevS) == Model.Shuffle(a[..], i)(s)
17+
}
18+
19+
}

src/Util/FisherYates/Implementation.dfy

Lines changed: 7 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -8,62 +8,25 @@ module FisherYates.Implementation {
88
import Monad
99
import Model
1010
import Uniform
11+
import Equivalence
1112

1213
trait {:termination false} Trait extends Interface.Trait {
1314

14-
method {:vcs_split_on_every_assert} Shuffle<T>(a: array<T>)
15+
method Shuffle<T>(a: array<T>)
1516
decreases *
1617
modifies `s, a
1718
ensures Model.Shuffle(old(a[..]))(old(s)) == Monad.Result(a[..], s)
1819
{
19-
ghost var prevASeq := a[..];
20-
ghost var prevI := 0;
21-
ghost var prevS := s;
20+
ghost var prevI, prevASeq, prevS := 0, a[..], s; // ghost
2221
if a.Length > 1 {
23-
var i := 0;
24-
while i < a.Length - 1
25-
decreases a.Length - 1 - i
26-
invariant prevI == if i == 0 then i else i - 1
27-
invariant prevI <= |prevASeq|
28-
invariant i <= |a[..]|
29-
invariant i <= a.Length - 1
30-
invariant |prevASeq| == |a[..]| == a.Length
31-
invariant Model.Shuffle(old(a[..]))(old(s)) == Model.Shuffle(prevASeq, prevI)(prevS)
32-
invariant Model.Shuffle(prevASeq, prevI)(prevS) == Model.Shuffle(a[..], i)(s)
22+
for i := 0 to a.Length - 1
23+
invariant Equivalence.LoopInvariant(prevI, i, a, prevASeq, old(a[..]), old(s), prevS, s)
3324
{
34-
prevI := i;
35-
prevASeq := a[..];
36-
prevS := s;
25+
prevI, prevASeq, prevS := i, a[..], s; // ghost
3726
var j := UniformIntervalSample(i, a.Length);
38-
assert prevASeq == a[..];
27+
assert prevASeq == a[..]; // ghost
3928
Swap(a, i, j);
40-
i := i + 1;
41-
assert Model.Shuffle(prevASeq, prevI)(prevS) == Model.Shuffle(a[..], i)(s) by {
42-
calc {
43-
Model.Shuffle(prevASeq, prevI)(prevS);
44-
Model.Shuffle(Model.Swap(prevASeq, prevI, Uniform.Model.IntervalSample(prevI, |prevASeq|)(prevS).value), prevI + 1)(Uniform.Model.IntervalSample(prevI, |prevASeq|)(prevS).rest);
45-
{ assert Uniform.Model.IntervalSample(prevI, |prevASeq|)(prevS).value == j;
46-
assert Uniform.Model.IntervalSample(prevI, |prevASeq|)(prevS).rest == s; }
47-
Model.Shuffle(Model.Swap(prevASeq, prevI, j), prevI + 1)(s);
48-
{ assert i == prevI + 1;
49-
assert Model.Swap(prevASeq, prevI, j) == a[..];
50-
}
51-
Model.Shuffle(a[..], i)(s);
52-
}
53-
}
5429
}
55-
56-
assert Model.Shuffle(old(a[..]))(old(s)) == Monad.Result(a[..], s) by {
57-
assert i == a.Length - 1;
58-
calc {
59-
Model.Shuffle(old(a[..]))(old(s));
60-
Model.Shuffle(prevASeq, prevI)(prevS);
61-
Model.Shuffle(a[..], i)(s);
62-
Monad.Return(a[..])(s);
63-
Monad.Result(a[..], s);
64-
}
65-
}
66-
6730
}
6831
}
6932

0 commit comments

Comments
 (0)