-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
681 additions
and
469 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,366 @@ | ||
interface Array[E: Library.Type] { | ||
rep type T | ||
|
||
func loc(a: T, i: Int) returns (r: Ref) | ||
func length(a: T) returns (l: Int) | ||
func first(r: Ref) returns (a: T) | ||
func second(r: Ref) returns (i: Int) | ||
|
||
auto axiom all_diff() | ||
ensures forall a:T, i: Int :: {loc(a, i)} first(loc(a, i)) == a && second(loc(a, i)) == i | ||
|
||
auto axiom len_nonneg() | ||
ensures forall a:T :: {length(a)} length(a) >= 0 | ||
|
||
field value: E | ||
|
||
val default: E | ||
|
||
val default_map: Map[Int, E] = {| i: Int :: default |} | ||
|
||
pred arr(a: T; m: Map[Int, E]) { | ||
(forall j: Int :: 0 <= j < length(a) ==> own(loc(a, j), value, m[j], 1.0)) | ||
&& (forall j: Int :: {m[j]} (0 > j || j >= length(a)) ==> m[j] == default) | ||
} | ||
|
||
proc alloc(len: Int, d: E) returns (a: T) | ||
requires 0 <= len | ||
ensures length(a) == len && arr(a, {| i: Int :: 0 <= i < len ? d : default |}) | ||
|
||
func injective(m: Map[Int, E], i: Int, j: Int) returns (res: Bool) | ||
{ | ||
forall i1: Int, i2: Int :: {m[i1], m[i2]} i <= i1 < i2 < j ==> m[i1] != m[i2] | ||
} | ||
|
||
func inverse_help(m: Map[Int, E], i: Int, j: Int, k: E, i1: Int) returns (res: Int) | ||
{ | ||
m[i1] == k && i1 < j ? i1 : (i1 < j ? inverse_help(m, i, j, k, i1+1) : i-1) | ||
} | ||
|
||
func inverse(m: Map[Int, E], i: Int, j: Int, k: E) returns (res: Int) | ||
{ | ||
inverse_help(m, i, j, k, i) | ||
} | ||
|
||
lemma invertable_help(m: Map[Int, E], i: Int, j: Int, i1: Int, i2: Int) | ||
requires injective(m, i, j) | ||
ensures i <= i2 <= i1 < j ==> inverse_help(m, i, j, m[i1], i2) == i1 | ||
{ | ||
if (i <= i2 <= i1 < j) { | ||
if (i2 < i1) { | ||
invertable_help(m, i, j, i1, i2+1); | ||
} | ||
} | ||
} | ||
|
||
auto lemma invertable() | ||
ensures forall m: Map[Int, E], i: Int, j: Int, i1: Int :: {injective(m, i, j), m[i1]} | ||
injective(m, i, j) && i <= i1 < j ==> inverse(m, i, j, m[i1]) == i1 | ||
{ | ||
assert forall m: Map[Int, E], i: Int, j: Int, i1: Int :: {injective(m, i, j), m[i1]} | ||
injective(m, i, j) && i <= i1 < j ==> inverse(m, i, j, m[i1]) == i1 with { | ||
if (injective(m, i, j) && i <= i1 < j) { | ||
invertable_help(m, i, j, i1, i); | ||
} | ||
} | ||
} | ||
|
||
lemma invertable2_help(m: Map[Int, E], i: Int, j: Int, k: E, i2: Int) | ||
ensures i <= i2 <= inverse_help(m, i, j, k, i2) < j ==> m[inverse_help(m, i, j, k, i2)] == k | ||
ensures i2 > inverse_help(m, i, j, k, i2) || inverse_help(m, i, j, k, i2) >= j ==> inverse_help(m, i, j, k, i2) == i-1 | ||
{ | ||
if (i2 < j) { | ||
invertable2_help(m, i, j, k, i2+1); | ||
} | ||
} | ||
|
||
auto lemma invertable2() | ||
ensures forall m: Map[Int, E], i: Int, j: Int, k: E :: {inverse(m, i, j, k)} | ||
(i <= inverse(m, i, j, k) < j ==> m[inverse(m, i, j, k)] == k) && | ||
(i > inverse(m, i, j, k) || inverse(m, i, j, k) >= j ==> inverse(m, i, j, k) == i-1) | ||
{ | ||
assert forall m: Map[Int, E], i: Int, j: Int, k: E :: {inverse(m, i, j, k)} | ||
(i <= inverse(m, i, j, k) < j ==> m[inverse(m, i, j, k)] == k) && | ||
(i > inverse(m, i, j, k) || inverse(m, i, j, k) >= j ==> inverse(m, i, j, k) == i-1) | ||
with { | ||
invertable2_help(m, i, j, k, i); | ||
} | ||
} | ||
|
||
lemma inverse_update_help(m: Map[Int, E], i: Int, j: Int, k: E, i1: Int, k2: E, i2: Int) | ||
requires inverse_help(m, i, j, k2, i2) < i2 || i1 < i2 || i1 >= j | ||
ensures inverse_help(m[i1 := k], i, j, k2, i2) == (k == k2 && i2 <= i1 < j ? i1 : inverse_help(m, i, j, k2, i2)) | ||
{ | ||
if (i2 < j) { | ||
inverse_update_help(m, i, j, k, i1, k2, i2+1); | ||
} | ||
} | ||
|
||
auto lemma inverse_update() | ||
ensures forall m: Map[Int, E], i: Int, j: Int, k: E, i1: Int, k2: E :: {inverse(m[i1 := k], i, j, k2)} | ||
inverse(m, i, j, k2) < i || i1 < i || i1 >= j ==> | ||
inverse(m[i1 := k], i, j, k2) == (k == k2 && i <= i1 < j ? i1 : inverse(m, i, j, k2)) | ||
{ | ||
assert forall m: Map[Int, E], i: Int, j: Int, k: E, i1: Int, k2: E :: {inverse(m[i1 := k], i, j, k2)} | ||
inverse(m, i, j, k2) < i || i1 < i || i1 >= j ==> | ||
inverse(m[i1 := k], i, j, k2) == (k == k2 && i <= i1 < j ? i1 : inverse(m, i, j, k2)) with { | ||
if (inverse(m, i, j, k2) < i || i1 < i || i1 >= j) { | ||
inverse_update_help(m, i, j, k, i1, k2, i); | ||
} | ||
} | ||
} | ||
|
||
func set_of_map(m: Map[Int, E], i: Int, j: Int) returns (res: Set[E]) | ||
{ | ||
{| k: E :: injective(m, i, j) && i <= inverse(m, i, j, k) < j |} //&& m[inverse(m, i, j, k)] == k |} | ||
} | ||
|
||
lemma injective_split() | ||
ensures forall m: Map[Int, E], i: Int, j: Int, l: Int :: {injective(m, i, l), injective(m, i, j)} | ||
i <= j <= l && injective(m, i, l) ==> injective(m, i, j) | ||
ensures forall m: Map[Int, E], i: Int, j: Int, l: Int :: {injective(m, i, l), injective(m, j, l)} | ||
i <= j <= l && injective(m, i, l) ==> injective(m, j, l) | ||
{} | ||
|
||
lemma set_of_map_split(m: Map[Int, E], i: Int, j: Int, l: Int) | ||
requires i <= j <= l && injective(m, i, l) | ||
ensures set_of_map(m, i, l) == set_of_map(m, i, j) ++ set_of_map(m, j, l) | ||
{ } | ||
|
||
func map_shift(m: Map[Int, E], src: Int, dst: Int, len: Int) | ||
returns (res: Map[Int, E]) | ||
{ | ||
{| i: Int :: i < dst || dst + len <= i ? m[i] : m[src + (i - dst)] |} | ||
} | ||
|
||
func map_copy(m1: Map[Int, E], m2: Map[Int, E], src: Int, dst: Int, len: Int) | ||
returns (res: Map[Int, E]) | ||
{ | ||
{| i: Int :: dst <= i < dst + len ? m2[src + (i - dst)] : m1[i] |} | ||
} | ||
|
||
lemma set_of_map_equal(m1: Map[Int, E], m2: Map[Int, E], i1: Int, i2: Int, len: Int) | ||
requires forall j: Int :: {m1[j]} i1 <= j < i1 + len ==> m1[j] == m2[j + (i2 - i1)] | ||
requires injective(m1, i1, i1 + len) && injective(m2, i2, i2 + len) | ||
ensures set_of_map(m1, i1, i1 + len) == set_of_map(m2, i2, i2 + len) | ||
{ | ||
if (0 < len) { | ||
set_of_map_equal(m1, m2, i1 + 1, i2 + 1, len - 1); | ||
} | ||
} | ||
|
||
lemma frame_set_of_map(m: Map[Int, E], i: Int, j: Int) | ||
requires i <= j | ||
requires injective(m, i, j) | ||
ensures forall i1: Int, k: E :: {set_of_map(m[i1 := k], i, j)} | ||
i1 < i || j <= i1 ==> set_of_map(m, i, j) == set_of_map(m[i1 := k], i, j) | ||
{ | ||
|
||
} | ||
|
||
// Shift a[src..src+len] to a[dst..dst+len] | ||
proc arr_shift(a: T, src: Int, dst: Int, len: Int, implicit ghost amap: Map[Int, E]) | ||
requires arr(a, amap) | ||
requires 0 <= src <= src + len <= length(a) && 0 <= dst <= dst + len <= length(a) | ||
ensures arr(a, map_shift(amap, src, dst, len)) | ||
{ | ||
if (src < dst) { | ||
var i: Int := len - 1; | ||
|
||
while (i >= 0) | ||
invariant arr(a, map_shift(amap, src + i + 1, dst + i + 1, len - i - 1)) | ||
invariant src < dst | ||
invariant 0 <= src <= src + len <= length(a) | ||
invariant 0 <= dst <= dst + len <= length(a) | ||
invariant -1 <= i < len | ||
{ | ||
unfold arr(a, map_shift(amap, src + i + 1, dst + i + 1, len - i - 1)); | ||
var tmp: E := loc(a, src + i).value; | ||
loc(a, dst + i).value := tmp; | ||
ghost var m : Map[Int, E] = map_shift(amap, src + i, dst + i, len - i); | ||
assert m == map_shift(amap, src + i + 1, dst + i + 1, len - i - 1)[dst + i := tmp]; | ||
i := i - 1; | ||
fold arr(a, map_shift(amap, src + i + 1, dst + i + 1, len - i - 1)); | ||
} | ||
} else if (src > dst) { | ||
var i: Int := 0; | ||
while (i < len) | ||
invariant arr(a, map_shift(amap, src, dst, i)) | ||
invariant src > dst | ||
invariant 0 <= src <= src + len <= length(a) | ||
invariant 0 <= dst <= dst + len <= length(a) | ||
invariant 0 <= i <= len | ||
{ | ||
unfold arr(a, map_shift(amap, src, dst, i)); | ||
var tmp: E := loc(a, src + i).value; | ||
loc(a, dst + i).value := tmp; | ||
ghost var m : Map[Int, E] = map_shift(amap, src, dst, i + 1); | ||
assert m == map_shift(amap, src, dst, i)[dst + i := tmp]; | ||
i := i + 1; | ||
fold arr(a, map_shift(amap, src, dst, i)); | ||
} | ||
} | ||
} | ||
|
||
// Copy a[src..src+len] to b[dst..dst+len] | ||
proc arr_copy(a: T, b: T, src: Int, dst: Int, len: Int, implicit ghost amap: Map[Int, E], implicit ghost bmap: Map[Int, E] ) | ||
requires arr(a, amap) && arr(b, bmap) | ||
requires 0 <= src <= src + len <= length(a) | ||
requires 0 <= dst <= dst + len <= length(b) | ||
ensures arr(a, amap) && arr(b, map_copy(bmap, amap, src, dst, len)) | ||
{ | ||
var i: Int := 0; | ||
|
||
while (i < len) | ||
invariant arr(a, amap) && arr(b, map_copy(bmap, amap, src, dst, i)) | ||
invariant 0 <= i <= len | ||
invariant 0 <= src <= src + len <= length(a) | ||
invariant 0 <= dst <= dst + len <= length(b) | ||
{ | ||
unfold arr(a, amap); | ||
var tmp: E := loc(a, src + i).value; | ||
fold arr(a, amap); | ||
unfold arr(b, map_copy(bmap, amap, src, dst, i)); | ||
loc(b, dst + i).value := tmp; | ||
ghost var m: Map[Int, E] = map_copy(bmap, amap, src, dst, i + 1); | ||
assert m == map_copy(bmap, amap, src, dst, i)[dst + i := tmp]; | ||
i := i + 1; | ||
fold arr(b, map_copy(bmap, amap, src, dst, i)); | ||
} | ||
} | ||
|
||
|
||
/* | ||
func sorted_map_seg(m: Map[Int, E], i: Int, j: Int) returns (res: Bool) | ||
{ | ||
forall i1: Int, i2: Int :: {m[i1], m[i2]} i <= i1 && i1 < i2 && i2 < j ==> lt(m[i1], m[i2]) | ||
} | ||
|
||
lemma sorted_injective() | ||
ensures forall m: Map[Int, E], i: Int, j: Int :: {sorted_map_seg(m, i, j)} | ||
sorted_map_seg(m, i, j) ==> injective(m, i, j) | ||
{ } | ||
|
||
lemma not_in_sorted_seg(m: Map[Int, E], i: Int, j: Int, k: E) | ||
requires sorted_map_seg(m, i, j) | ||
ensures i >= j || lt(k, m[i]) || lt(m[j-1], k) ==> k !in set_of_map(m, i, j) | ||
{ | ||
} | ||
|
||
|
||
auto lemma map_find_content_set() | ||
ensures forall m: Map[Int, E], i: Int, j: Int, k: E :: {sorted_map_seg(m, i, j), map_find(m, i, j, k)} | ||
i <= j && sorted_map_seg(m, i, j) ==> | ||
k !in set_of_map(m, i, map_find(m, i, j, k)) && | ||
k !in set_of_map(m, map_find(m, i, j, k) + 1, j) | ||
{ } | ||
|
||
lemma map_find_in_set(m: Map[Int, E], i: Int, j: Int, k: E) | ||
requires i <= j | ||
requires sorted_map_seg(m, i, j) | ||
ensures k in set_of_map(m, i, j) ==> map_find(m, i, j, k) < j && m[map_find(m, i, j, k)] == k | ||
ensures k !in set_of_map(m, i, j) ==> map_find(m, i, j, k) == j || lt(k, m[map_find(m, i, j, k)]) | ||
{ | ||
//map_find_content_set(m, i, j, k); | ||
} | ||
|
||
lemma map_insert_content_set(m: Map[Int, E], m1: Map[Int, E], idx: Int, k: E, len: Int, new_len: Int) | ||
//requires sorted_map_seg(m, 0, len) | ||
requires injective(m, 0, len) | ||
requires idx == map_find(m, 0, len, k) | ||
requires 0 <= idx <= len | ||
requires k in set_of_map(m, 0, len) ==> new_len == len && m1 == m | ||
requires k !in set_of_map(m, 0, len) ==> new_len == len + 1 && m1 == map_shift(m, idx, idx + 1, len - idx)[idx := k] | ||
ensures set_of_map(m1, 0, new_len) == set_of_map(m, 0, len) ++ {| k |} | ||
{ | ||
if (m[idx] == k && idx < len) { | ||
//in_set_of_map(m, 0, len); | ||
return; | ||
} | ||
//assume false; | ||
var ms: Map[Int, E] := map_shift(m, idx, idx + 1, len - idx); | ||
|
||
// prove set_of_map(m, 0, len) == set_of_map(ms, 0, idx) ++ set_of_array(ms, idx + 1, len + 1); | ||
|
||
//set_of_map_split(m, 0, idx, len); | ||
set_of_map_equal(m, ms, 0, 0, idx); | ||
set_of_map_equal(m, ms, idx, idx + 1, len - idx); | ||
|
||
// prove set_of_map(m1, 0, new_len) == set_of_array(ms, 0, idx) ++ {k} ++ set_of_map(ms, idx + 1, len + 1) | ||
//frame_set_of_map(ms, 0, idx); | ||
//frame_set_of_map(ms, idx + 1, len + 1); | ||
set_of_map_split(m1, 0, idx, len + 1); | ||
}*/ | ||
|
||
/* | ||
func sorted_map_seg(m: Map[Int, E], i: Int, j: Int) returns (res: Bool) | ||
{ | ||
forall i1: Int, i2: Int :: {m[i1], m[i2]} i <= i1 && i1 < i2 && i2 < j ==> lt(m[i1], m[i2]) | ||
} | ||
|
||
func map_find(m: Map[Int, E], i: Int, j: Int, k: E) returns (idx: Int) | ||
/*ensures | ||
i <= j && sorted_map_seg(m, i, j) ==> | ||
i <= idx <= j && | ||
(m[idx] == k || idx == j || lt(k, m[idx])) && | ||
(i < idx ==> lt(m[idx - 1], k))*/ | ||
{ | ||
i < j && lt(m[i], k) ? map_find(m, i + 1, j, k) : i | ||
} | ||
|
||
lemma map_find_spec(m: Map[Int, E], i: Int, j: Int, k: E) | ||
ensures i <= j && sorted_map_seg(m, i, j) ==> | ||
i <= map_find(m, i, j, k) && map_find(m, i, j, k) <= j && | ||
(m[map_find(m, i, j, k)] == k || map_find(m, i, j, k) == j || lt(k, m[map_find(m, i, j, k)])) && | ||
(i < map_find(m, i, j, k) ==> lt(m[map_find(m, i, j, k) - 1], k)) | ||
{ | ||
if (i < j && sorted_map_seg(m, i, j)) { | ||
map_find_spec(m, i+1, j, k); | ||
} | ||
} | ||
|
||
auto lemma map_find_spec_auto() | ||
ensures forall m: Map[Int, E], i: Int, j: Int, k: E :: i <= j && sorted_map_seg(m, i, j) ==> | ||
i <= map_find(m, i, j, k) && map_find(m, i, j, k) <= j && | ||
(m[map_find(m, i, j, k)] == k || map_find(m, i, j, k) == j || lt(k, m[map_find(m, i, j, k)])) && | ||
(i < map_find(m, i, j, k) ==> lt(m[map_find(m, i, j, k) - 1], k)) | ||
{ | ||
assert forall m: Map[Int, E], i: Int, j: Int, k: E :: i <= j && sorted_map_seg(m, i, j) ==> | ||
i <= map_find(m, i, j, k) && map_find(m, i, j, k) <= j && | ||
(m[map_find(m, i, j, k)] == k || map_find(m, i, j, k) == j || lt(k, m[map_find(m, i, j, k)])) && | ||
(i < map_find(m, i, j, k) ==> lt(m[map_find(m, i, j, k) - 1], k)) with { | ||
map_find_spec(m, i, j, k); | ||
} | ||
} | ||
|
||
auto lemma sorted_injective() | ||
ensures forall m: Map[Int, E], i: Int, j: Int :: {sorted_map_seg(m, i, j)} | ||
sorted_map_seg(m, i, j) ==> injective(m, i, j) | ||
{ } | ||
|
||
lemma map_delete_content_set(m: Map[Int, E], m1: Map[Int, E], len: Int, new_len: Int, idx: Int, k: E) | ||
requires sorted_map_seg(m, 0, len) | ||
requires idx == map_find(m, 0, len, k) | ||
requires 0 <= idx <= len | ||
requires k !in set_of_map(m, 0, len) ==> new_len == len && m1 == m | ||
requires k in set_of_map(m, 0, len) ==> new_len == len - 1 && m1 == map_shift(m, idx + 1, idx, len - (idx + 1)) | ||
ensures set_of_map(m1, 0, new_len) == set_of_map(m, 0, len) -- {|k|} | ||
{ | ||
//map_find_content_set(m, 0, len, idx, k); | ||
//set_of_map_split(m, 0, idx, len); | ||
|
||
if (idx == len || m[idx] != k) { | ||
return; | ||
} | ||
|
||
// prove: set_of_map(m, 0, len) -- {k} == set_of_map(m1, 0, idx - 1) ++ set_of_map(m1, idx - 1, len - 1) | ||
set_of_map_equal(m, m1, 0, 0, idx); | ||
set_of_map_equal(m, m1, idx + 1, idx, len - (idx + 1)); | ||
|
||
//not_in_sorted_seg(m, 0, idx - 1, k); | ||
//not_in_sorted_seg(m, idx + 1, len, k); | ||
|
||
set_of_map_split(m1, 0, idx, len - 1); | ||
}*/ | ||
|
||
} |
Oops, something went wrong.