На моей установке Дафни отключается при попытке проверить заданный инвариант цикла. Тем не менее, я думаю, что вы можете сделать то, что вы хотите, заменив этот инвариант цикла более сильными инвариантами:
invariant multiset(a[..i])[key] == keyCount
invariant b <==> (keyCount == 1)
Первые утверждают, что в мультимножестве, содержащем первые i элементов a, количество ключей равнок вычисленному keyCount
. Второй относится b
и keyCount
. Полное решение приведено ниже:
method only_once<a(==)>(a: array<a>, key: a)
{
var i := 0;
var b := false;
var keyCount := 0;
while i < a.Length
invariant 0 <= i <= a.Length
invariant multiset(a[..i])[key] == keyCount
invariant b <==> (keyCount == 1)
{
ghost var preCount := keyCount;
if (a[i] == key)
{ keyCount := keyCount + 1; }
if (keyCount == 1)
{ b := true; }
else
{ b := false; }
i := i + 1;
}
assert a[..a.Length] == a[..];
assert b <==> multiset(a[..])[key] == 1;
}
Я считаю, что последнее утверждение - это то, что вы хотите. Я не уверен, зачем Дафни нужен второй до последнего утверждения a[..a.Length] == a[..]
, но его удаление приводит к сбою проверки последнего утверждения.