-
Notifications
You must be signed in to change notification settings - Fork 1
/
008-sum_product.dfy
62 lines (56 loc) · 1.56 KB
/
008-sum_product.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
function sum(s: seq<int>) : int {
if |s| == 0 then 0 else s[0] + sum(s[1..])
}
lemma sum_prop(s: seq<int>)
requires |s| > 0
ensures sum(s) == sum(s[..|s| - 1]) + s[ |s| - 1 ]
{
if (|s| > 1) {
assert (s[1..][..|s[1..]| - 1]) == s[1..|s| - 1];
}
}
function prod(s: seq<int>) : int {
if |s| == 0 then 1 else s[0] * prod(s[1..])
}
lemma prod_prop(s: seq<int>)
requires |s| > 0
ensures prod(s) == prod(s[..|s| - 1]) * s[ |s| - 1 ]
{
if (|s| > 1) {
assert (s[1..][..|s[1..]| - 1]) == s[1..|s| - 1];
}
}
method sum_product(numbers: seq<int>) returns (s : int, p : int)
// post-condition-start
ensures s == sum(numbers)
ensures p == prod(numbers)
// post-condition-end
{
// impl-start
assert numbers[..|numbers|] == numbers; // assert-line
s := 0;
p := 1;
for i := 0 to |numbers|
// invariants-start
invariant s == sum(numbers[..i])
invariant p == prod(numbers[..i])
// invariants-end
{
// assert-start
assert sum(numbers[..i + 1]) == sum(numbers[..i]) + numbers[i] by {
assert numbers[..i+1][..i] == numbers[..i]; // assert-line
sum_prop(numbers[..i + 1]);
}
// assert-end
s := s + numbers[i];
// assert-start
assert prod(numbers[..i + 1]) == prod(numbers[..i]) * numbers[i] by {
assert numbers[..i+1][..i] == numbers[..i]; // assert-line
prod_prop(numbers[..i + 1]);
}
// assert-end
p := p * numbers[i];
}
return s, p;
// impl-end
}