В вашем первом фрагменте кода, когда while
l oop выходит, Дафни знает только это !(idx < n)
. Следовательно, он может сделать вывод, что idx > 0
. Однако Дафни ничего не знает о переменной cnt
на данный момент, поэтому ваше второе утверждение не выполняется.
Во втором фрагменте кода, когда while
l oop завершается, все Дафни он знает, что это !(idx < n && cnt < n)
(опять же, отрицание условия на while
l oop). Это эквивалент idx > n || cnt > n
. Отсюда Дафни может вывести idx > 0 || cnt > 0
, но он не сможет доказать ни idx > 0
, ни cnt > 0
самостоятельно.
Чтобы исправить это, вам нужно добавить некоторую связь между переменными cnt
и idx
, которые Дафни может проверить, а затем использовать.
while idx < n && cnt < n
decreases n - idx
decreases n - cnt
invariant idx == cnt
{
idx := idx + 1;
cnt := cnt + 1;
}
Дополнительная строка invariant
сообщает Дафни проверку, что idx == cnt
будет сохраняться на каждой итерации l oop, и тогда он может использовать этот факт в конце. Однако Дафни не узнает, чтобы рассмотреть факт idx == cnt
, если вы не скажете ему об этом.
(В качестве примечания вы увидите, что Дафни может самостоятельно определить, что n > 0
содержится в конце while
l oop, даже если вы не указываете его явно, как в invariant
. Это потому, что n
не изменяется в тело while l oop, поэтому Дафни автоматически перенесет тот факт, что n > 0
с самого начала.)