Как мне доказать, что цикл while завершается в Dafny?

#dafny

#dafny

Вопрос:

Я новичок в Dafny и изучаю его. Для следующего кода Dafny

 method Dummy(s: seq<nat>) returns (ret: nat)
    requires forall k :: 0 <= k < |s| ==> s[k] > 0
{
    ret := 0;
    var se := s;

    while |se| > 0
    {
        // Pick a random index of the seq.
        var i :| 0 <= i < |se|;
        if se[i] == 1 {
            // Remove the seq element if it is 1.
            se := se[..i]   se[i   1..];
        } else {
            // Replace the seq element with 3 occurences of 1.
            se := [1, 1, 1]   se[..i]   se[i   1..];
        }
    }

    return;
}
  

Я вижу жалобы, которые

 decreases |se| - 0Dafny VSCode
cannot prove termination; try supplying a decreases clause for the loopDafny VSCode
  

Я знаю, что для доказательства завершения, как правило, я должен предоставить decreases предложение. Я просто не могу найти, что вставить в decreases предложение в этом случае. Проще говоря

 decreases |se|
  

это не сработает, так как в else части if инструкции seq размер может фактически увеличиться.

Если это доказательство с помощью пера и бумаги, я хотел бы утверждать, что для любого элемента, равного 1, он будет удален; и для любого элемента, который больше 1, он будет заменен на 3 появления 1, которые все равно будут удалены окончательно. Следовательно se , в конце будет пусто, и цикл завершится.

Как мне преобразовать его в коды, с которыми согласится Dafny?

Ответ №1:

Ключ в том, чтобы ввести функцию, которую я называю «общий потенциал», которая вычисляет, сколько итераций потребуется циклу для обработки списка. Его определение таково: «для каждого 1 в списке добавьте 1 к общему потенциалу, для каждого не-1 в списке добавьте 4 к общему потенциалу». Затем мы сделаем decreases предложение общим потенциалом. Таким образом, когда 1 удаляется, потенциал уменьшается на 1, а когда не-1 удаляется и заменяется тремя единицами, потенциал также уменьшается на 1.

Существует некоторая дополнительная работа, чтобы убедить Dafny в том, что общий потенциал фактически уменьшается на каждой итерации цикла. Вам понадобится несколько лемм о том, как общий потенциал связан с разделением и добавлением последовательностей.

Комментарии:

1. Этот ответ настолько потрясающий — он не только отвечает на вопрос, но и предварительно ответил на мой следующий вопрос в том же примере проблемы! Спасибо за ваш подробный пример и объяснение!!!