predicate derangement(s: seq<nat>) {
forall i :: 0 <= i < |s| ==> s[i] != i
predicate permutation(s: seq<nat>) {
forall i :: 0 <= i < |s| ==> i in s
function multisetRange(n: nat): multiset<nat> {
predicate distinct<A(==)>(s: seq<A>) {
forall x,y :: x != y && 0 <= x <= y < |s| ==> s[x] != s[y]
var t4 := seq(3, i => i);
var test3 := multisetRange(3);
assert multiset(tests) == multisetRange(3);
assert derangement(tests);
assert permutation(tests);
assert permutation(tests2);
method {:timelimit 40} end(links: seq<nat>)
requires permutation(links)
requires derangement(links)
assume forall x :: x in links ==> 0 <= x < |links|;
assume forall x :: x in links ==> multiset(links)[x] ==1;
var qAct: nat := links[0];
assert links[0] in links;
ghost var indices: multiset<nat> := multiset{0};
ghost var visited: multiset<nat> := multiset{};
invariant 0 <= oldIndex < |links|
invariant qAct == links[oldIndex]
invariant oldIndex in indices
invariant indices == visited + multiset{0}
invariant forall x :: x in visited ==> exists k :: 0 <= k < |links| && links[k] == x && k in indices
invariant qAct !in visited
invariant 0 <= qAct < |links|
decreases multiset(links) - visited
ghost var oldVisit := visited;
ghost var oldqAct := qAct;
ghost var oldOldIndex := oldIndex;
visited := visited + multiset{qAct};
indices := indices + multiset{qAct};
assert oldqAct in visited;
assert forall x :: x in visited ==> exists k :: 0 <= k < |links| && links[k] == x && k in indices;