-
Notifications
You must be signed in to change notification settings - Fork 1
/
111-histogram.dfy
65 lines (63 loc) · 2.26 KB
/
111-histogram.dfy
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
type BiggestMap = map<int, int>
method count(a: seq<int>) returns (biggest: BiggestMap)
// post-conditions-start
ensures forall i :: 0 <= i < |a| && a[i] in biggest ==>
biggest[a[i]] == |set j | 0 <= j < |a| && a[j] == a[i]|
ensures forall i, j :: 0 <= i < |a| && 0 <= j < |a| && a[i] in biggest ==>
biggest[a[i]] >= |set k | 0 <= k < |a| && a[k] == a[j]|
ensures forall i, j :: 0 <= i < |a| && 0 <= j < |a| && a[i] in biggest && a[j] in biggest ==>
biggest[a[i]] == biggest[a[j]]
// post-conditions-end
{
// impl-start
if |a| == 0 {
return map[];
}
var cnt := map[];
ghost var positions := map[];
var i := 0;
while i < |a|
// invariants-start
invariant 0 <= i <= |a|
invariant forall j :: 0 <= j < i ==> a[j] in positions && positions[a[j]] == set k | 0 <= k < i && a[k] == a[j]
invariant forall j :: 0 <= j < i ==> a[j] in cnt && cnt[a[j]] == |positions[a[j]]|
invariant forall j :: j in positions ==> forall k :: k in positions[j] ==> k < i
invariant forall x :: x in positions ==> x in a[..i]
invariant forall x :: x in positions ==> x in cnt && cnt[x] == |positions[x]|
invariant forall x :: x in cnt ==> x in positions
// invariants-end
{
if a[i] in cnt {
ghost var pre := positions[a[i]];
positions := positions[a[i] := pre + {i}];
cnt := cnt[a[i] := cnt[a[i]] + 1];
} else {
positions := positions[a[i] := {i}];
cnt := cnt[a[i] := 1];
}
i := i + 1;
}
var maxCount := cnt[a[0]];
biggest := map[a[0] := maxCount];
i := 1;
while i < |a|
// invariants-start
invariant 0 <= i <= |a|
invariant forall j :: 0 <= j < |a| ==> a[j] in cnt
invariant forall j :: 0 <= j < i ==> a[j] in cnt && maxCount >= cnt[a[j]]
invariant exists j :: 0 <= j < i && a[j] in cnt && cnt[a[j]] == maxCount
invariant forall j :: 0 <= j < i ==> cnt[a[j]] == maxCount ==> a[j] in biggest
invariant forall x :: x in biggest ==> x in cnt && cnt[x] == maxCount
invariant forall x :: x in biggest ==> biggest[x] == cnt[x]
// invariants-end
{
if cnt[a[i]] > maxCount {
maxCount := cnt[a[i]];
biggest := map[a[i] := maxCount];
} else if cnt[a[i]] == maxCount {
biggest := biggest[a[i] := maxCount];
}
i := i + 1;
}
// impl-end
}