Skip to content

Commit aee6641

Browse files
committed
completed programs extract from !11
see original commits at secure-foundations#11 coauthored by @WeetHet
1 parent d50835b commit aee6641

17 files changed

+1120
-18
lines changed

tasks/human_eval_012.rs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,41 @@ use vstd::prelude::*;
99

1010
verus! {
1111

12-
// TODO: Put your solution (the specification, implementation, and proof) to the task here
12+
fn longest(strings: &Vec<Vec<u8>>) -> (result: Option<&Vec<u8>>)
13+
ensures
14+
match result {
15+
None => strings.len() == 0,
16+
Some(s) => {
17+
(forall|i: int| #![auto] 0 <= i < strings.len() ==> s.len() >= strings[i].len())
18+
&& (exists|i: int|
19+
#![auto]
20+
(0 <= i < strings.len() && s == strings[i] && (forall|j: int|
21+
#![auto]
22+
0 <= j < i ==> strings[j].len() < s.len())))
23+
},
24+
},
25+
{
26+
if strings.len() == 0 {
27+
return None;
28+
}
29+
let mut result: &Vec<u8> = &strings[0];
30+
let mut pos = 0;
31+
32+
for i in 1..strings.len()
33+
invariant
34+
0 <= pos < i,
35+
result == &strings[pos as int],
36+
exists|i: int| 0 <= i < strings.len() && strings[i] == result,
37+
forall|j: int| #![auto] 0 <= j < i ==> strings[j].len() <= result.len(),
38+
forall|j: int| #![auto] 0 <= j < pos ==> strings[j].len() < result.len(),
39+
{
40+
if result.len() < strings[i].len() {
41+
result = &strings[i];
42+
pos = i;
43+
}
44+
}
45+
Some(result)
46+
}
1347

1448
} // verus!
1549
fn main() {}

tasks/human_eval_014.rs

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,53 @@ use vstd::prelude::*;
99

1010
verus! {
1111

12-
// TODO: Put your solution (the specification, implementation, and proof) to the task here
12+
fn all_prefixes(s: &Vec<u8>) -> (prefixes: Vec<Vec<u8>>)
13+
ensures
14+
prefixes.len() == s.len(),
15+
forall|i: int| #![auto] 0 <= i < s.len() ==> prefixes[i]@ == s@.subrange(0, i + 1),
16+
{
17+
let mut prefixes: Vec<Vec<u8>> = vec![];
18+
let mut prefix = vec![];
19+
assert(forall|i: int|
20+
#![auto]
21+
0 <= i < prefix.len() ==> prefix@.index(i) == prefix@.subrange(
22+
0,
23+
prefix.len() as int,
24+
).index(i));
25+
26+
assert(prefix@ == prefix@.subrange(0, 0));
27+
assert(forall|i: int|
28+
#![auto]
29+
0 <= i < prefix.len() ==> prefix@.index(i) == s@.subrange(0, prefix.len() as int).index(i));
30+
assert(prefix@ == s@.subrange(0, 0));
31+
for i in 0..s.len()
32+
invariant
33+
prefixes.len() == i,
34+
prefix.len() == i,
35+
forall|j: int| #![auto] 0 <= j < i ==> prefixes[j]@ == s@.subrange(0, j + 1),
36+
prefix@ == s@.subrange(0, i as int),
37+
prefix@ == prefix@.subrange(0, i as int),
38+
{
39+
let ghost pre_prefix = prefix;
40+
prefix.push(s[i]);
41+
assert(pre_prefix@.subrange(0, i as int) == pre_prefix@ && prefix@.subrange(0, i as int)
42+
== pre_prefix@.subrange(0, i as int));
43+
assert(prefix@.subrange(0, i as int) == s@.subrange(0, i as int));
44+
assert(prefix[i as int] == s@.subrange(0, i + 1).index(i as int));
45+
46+
assert(forall|j: int|
47+
#![auto]
48+
0 <= j < i + 1 ==> prefix@.index(j) == prefix@.subrange(0, (i + 1) as int).index(j));
49+
assert(prefix@ == prefix@.subrange(0, (i + 1) as int));
50+
assert(forall|j: int|
51+
#![auto]
52+
0 <= j < i + 1 ==> prefix@.index(j) == s@.subrange(0, (i + 1) as int).index(j));
53+
assert(prefix@ == s@.subrange(0, (i + 1) as int));
54+
55+
prefixes.push(prefix.clone());
56+
}
57+
return prefixes;
58+
}
1359

1460
} // verus!
1561
fn main() {}

tasks/human_eval_034.rs

Lines changed: 180 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,190 @@ HumanEval/34
55
/*
66
### VERUS BEGIN
77
*/
8+
use vstd::calc;
89
use vstd::prelude::*;
10+
use vstd::seq_lib::lemma_multiset_commutative;
11+
use vstd::seq_lib::lemma_seq_contains_after_push;
912

1013
verus! {
1114

12-
// TODO: Put your solution (the specification, implementation, and proof) to the task here
15+
proof fn swap_preserves_multiset_helper(s: Seq<i32>, i: int, j: int)
16+
requires
17+
0 <= i < j < s.len(),
18+
ensures
19+
(s.take(j + 1)).to_multiset() =~= s.take(i).to_multiset().add(
20+
s.subrange(i + 1, j).to_multiset(),
21+
).insert(s.index(j)).insert(s.index(i)),
22+
{
23+
let fst = s.take(i);
24+
let snd = s.subrange(i + 1, j);
25+
26+
assert((s.take(j + 1)).to_multiset() =~= fst.to_multiset().insert(s.index(i)).add(
27+
snd.to_multiset().insert(s.index(j)),
28+
)) by {
29+
assert(s.take(i + 1).to_multiset() =~= fst.to_multiset().insert(s.index(i))) by {
30+
fst.to_multiset_ensures();
31+
assert(fst.push(s.index(i)) =~= s.take(i + 1));
32+
}
33+
assert(s.subrange(i + 1, j + 1).to_multiset() =~= snd.to_multiset().insert(s.index(j))) by {
34+
snd.to_multiset_ensures();
35+
assert(snd.push(s.index(j)) =~= s.subrange(i + 1, j + 1));
36+
}
37+
lemma_multiset_commutative(s.take(i + 1), s.subrange(i + 1, j + 1));
38+
assert(s.take(i + 1) + s.subrange(i + 1, j + 1) =~= s.take(j + 1));
39+
}
40+
}
41+
42+
// Helper lemma to prove that swapping two elements doesn't change the multiset
43+
proof fn swap_preserves_multiset(s1: Seq<i32>, s2: Seq<i32>, i: int, j: int)
44+
requires
45+
0 <= i < j < s1.len() == s2.len(),
46+
forall|x: int| 0 <= x < s1.len() && x != i && x != j ==> s1.index(x) == s2.index(x),
47+
s1.index(i) == s2.index(j),
48+
s1.index(j) == s2.index(i),
49+
ensures
50+
s1.to_multiset() == s2.to_multiset(),
51+
{
52+
calc! {
53+
(==)
54+
s1.to_multiset(); {
55+
lemma_multiset_commutative(s1.take(j + 1), s1.skip(j + 1));
56+
assert(s1 =~= s1.take(j + 1) + s1.skip(j + 1));
57+
}
58+
s1.take(j + 1).to_multiset().add(s1.skip(j + 1).to_multiset()); {
59+
assert(s1.take(j + 1).to_multiset() =~= s2.take(j + 1).to_multiset()) by {
60+
assert(s1.take(i) == s2.take(i));
61+
assert(s1.subrange(i + 1, j) =~= (s2.subrange(i + 1, j)));
62+
swap_preserves_multiset_helper(s1, i, j);
63+
swap_preserves_multiset_helper(s2, i, j);
64+
}
65+
assert(s1.skip(j + 1).to_multiset() =~= s2.skip(j + 1).to_multiset()) by {
66+
assert(s1.skip(j + 1) =~= s2.skip(j + 1));
67+
}
68+
}
69+
s2.take(j + 1).to_multiset().add(s2.skip(j + 1).to_multiset()); {
70+
lemma_multiset_commutative(s2.take(j + 1), s2.skip(j + 1));
71+
assert(s2 =~= s2.take(j + 1) + s2.skip(j + 1));
72+
}
73+
s2.to_multiset();
74+
}
75+
}
76+
77+
fn sort_seq(s: &Vec<i32>) -> (ret: Vec<i32>)
78+
ensures
79+
forall|i: int, j: int| 0 <= i < j < ret@.len() ==> ret@.index(i) <= ret@.index(j),
80+
ret@.len() == s@.len(),
81+
s@.to_multiset() == ret@.to_multiset(),
82+
{
83+
let mut sorted = s.clone();
84+
let mut i: usize = 0;
85+
while i < sorted.len()
86+
invariant
87+
i <= sorted.len(),
88+
forall|j: int, k: int| 0 <= j < k < i ==> sorted@.index(j) <= sorted@.index(k),
89+
s@.to_multiset() == sorted@.to_multiset(),
90+
forall|j: int, k: int|
91+
0 <= j < i <= k < sorted@.len() ==> sorted@.index(j) <= sorted@.index(k),
92+
sorted@.len() == s@.len(),
93+
decreases (sorted.len() - i),
94+
{
95+
let mut min_index: usize = i;
96+
let mut j: usize = i + 1;
97+
while j < sorted.len()
98+
invariant
99+
i <= min_index < j <= sorted.len(),
100+
forall|k: int| i <= k < j ==> sorted@.index(min_index as int) <= sorted@.index(k),
101+
decreases (sorted.len() - j),
102+
{
103+
if sorted[j] < sorted[min_index] {
104+
min_index = j;
105+
}
106+
j += 1;
107+
}
108+
if min_index != i {
109+
let ghost old_sorted = sorted@;
110+
let curr_val = sorted[i];
111+
let min_val = sorted[min_index];
112+
sorted.set(i, min_val);
113+
114+
sorted.set(min_index, curr_val);
115+
116+
proof {
117+
swap_preserves_multiset(old_sorted, sorted@, i as int, min_index as int);
118+
assert(old_sorted.to_multiset() =~= sorted@.to_multiset());
119+
}
120+
}
121+
i += 1;
122+
}
123+
sorted
124+
}
125+
126+
fn unique_sorted(s: Vec<i32>) -> (result: Vec<i32>)
127+
requires
128+
forall|i: int, j: int| 0 <= i < j < s.len() ==> s[i] <= s[j],
129+
ensures
130+
forall|i: int, j: int| 0 <= i < j < result.len() ==> result[i] < result[j],
131+
forall|i: int| #![auto] 0 <= i < result.len() ==> s@.contains(result[i]),
132+
forall|i: int| #![trigger s[i]] 0 <= i < s.len() ==> result@.contains(s[i]),
133+
{
134+
let mut result: Vec<i32> = vec![];
135+
for i in 0..s.len()
136+
invariant
137+
forall|i: int, j: int| 0 <= i < j < s.len() ==> s[i] <= s[j],
138+
forall|k: int, l: int| 0 <= k < l < result.len() ==> result[k] < result[l],
139+
forall|k: int|
140+
#![trigger result[k]]
141+
0 <= k < result.len() ==> (exists|m: int| 0 <= m < i && result[k] == s[m]),
142+
forall|m: int| #![trigger s[m]] 0 <= m < i ==> result@.contains(s[m]),
143+
{
144+
let ghost pre = result;
145+
if result.len() == 0 || result[result.len() - 1] != s[i] {
146+
assert(result.len() == 0 || result[result.len() - 1] < s[i as int]);
147+
result.push(s[i]);
148+
assert forall|m: int| #![trigger s[m]] 0 <= m < i implies result@.contains(s[m]) by {
149+
assert(pre@.contains(s@[m]));
150+
lemma_seq_contains_after_push(pre@, s@[i as int], s@[m]);
151+
};
152+
}
153+
assert(forall|m: int|
154+
#![trigger result@[m], pre@[m]]
155+
0 <= m < pre.len() ==> pre@.contains(result@[m]) ==> result@.contains(pre@[m])) by {
156+
assert(forall|m: int| 0 <= m < pre.len() ==> result@[m] == pre@[m]);
157+
}
158+
assert(result@.contains(s[i as int])) by {
159+
assert(result[result.len() - 1] == s[i as int]);
160+
}
161+
}
162+
result
163+
}
164+
165+
fn unique(s: Vec<i32>) -> (result: Vec<i32>)
166+
ensures
167+
forall|i: int, j: int| 0 <= i < j < result.len() ==> result[i] < result[j],
168+
forall|i: int| #![auto] 0 <= i < result.len() ==> s@.contains(result[i]),
169+
forall|i: int| #![trigger s[i]] 0 <= i < s.len() ==> result@.contains(s[i]),
170+
{
171+
let sorted = sort_seq(&s);
172+
assert(forall|i: int| #![auto] 0 <= i < sorted.len() ==> s@.contains(sorted[i])) by {
173+
assert(forall|i: int|
174+
#![auto]
175+
0 <= i < sorted.len() ==> sorted@.to_multiset().contains(sorted[i])) by {
176+
sorted@.to_multiset_ensures();
177+
}
178+
assert(forall|i: int|
179+
#![auto]
180+
0 <= i < sorted.len() ==> s@.to_multiset().contains(sorted[i]));
181+
s@.to_multiset_ensures();
182+
}
183+
assert(forall|i: int| #![trigger s[i]] 0 <= i < s.len() ==> sorted@.contains(s[i])) by {
184+
assert(forall|i: int| #![auto] 0 <= i < s.len() ==> s@.to_multiset().contains(s[i])) by {
185+
s@.to_multiset_ensures();
186+
}
187+
assert(forall|i: int| #![auto] 0 <= i < s.len() ==> sorted@.to_multiset().contains(s[i]));
188+
sorted@.to_multiset_ensures();
189+
}
190+
unique_sorted(sorted)
191+
}
13192

14193
} // verus!
15194
fn main() {}

tasks/human_eval_035.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,25 @@ use vstd::prelude::*;
99

1010
verus! {
1111

12-
// TODO: Put your solution (the specification, implementation, and proof) to the task here
12+
fn max_element(a: &Vec<i32>) -> (max: i32)
13+
requires
14+
a.len() > 0,
15+
ensures
16+
forall|i: int| 0 <= i < a.len() ==> a[i] <= max,
17+
exists|i: int| 0 <= i < a.len() && a[i] == max,
18+
{
19+
let mut max = a[0];
20+
for i in 1..a.len()
21+
invariant
22+
forall|j: int| 0 <= j < i ==> a[j] <= max,
23+
exists|j: int| 0 <= j < i && a[j] == max,
24+
{
25+
if a[i] > max {
26+
max = a[i];
27+
}
28+
}
29+
max
30+
}
1331

1432
} // verus!
1533
fn main() {}

tasks/human_eval_043.rs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,42 @@ use vstd::prelude::*;
99

1010
verus! {
1111

12-
// TODO: Put your solution (the specification, implementation, and proof) to the task here
12+
#[verifier::loop_isolation(false)]
13+
fn pairs_sum_to_zero(nums: &[i32], target: i32) -> (found: bool)
14+
requires
15+
nums.len() >= 2,
16+
forall|i: int, j: int|
17+
0 <= i < j < nums.len() ==> nums[i] + nums[j] <= i32::MAX && nums[i] + nums[j]
18+
>= i32::MIN,
19+
ensures
20+
found <==> exists|i: int, j: int| 0 <= i < j < nums.len() && nums[i] + nums[j] == target,
21+
{
22+
let mut i = 0;
23+
24+
while i < nums.len()
25+
invariant
26+
0 <= i <= nums.len(),
27+
forall|u: int, v: int| 0 <= u < v < nums.len() && u < i ==> nums[u] + nums[v] != target,
28+
decreases nums.len() - i,
29+
{
30+
let mut j = i + 1;
31+
while j < nums.len()
32+
invariant
33+
0 <= i < j <= nums.len(),
34+
forall|u: int, v: int|
35+
0 <= u < v < nums.len() && u < i ==> nums[u] + nums[v] != target,
36+
forall|u: int| i < u < j ==> nums[i as int] + nums[u] != target,
37+
decreases nums.len() - j,
38+
{
39+
if nums[i] + nums[j] == target {
40+
return true;
41+
}
42+
j = j + 1;
43+
}
44+
i = i + 1;
45+
}
46+
false
47+
}
1348

1449
} // verus!
1550
fn main() {}

0 commit comments

Comments
 (0)