Давайте на время забудем greater
и просто посмотрим, чего вы пытаетесь достичь. После вызова Max
в Main
вы знаете следующее (из постусловия Max
):
res >= 4
res >= 5
forall x :: x >= 4 && x >= 5 ==> x >= res
Вы пытаетесь доказать res == 5
из этого. Вторая из этих трех вещей сразу дает вам половину этого равенства, поэтому все, что вам нужно сделать, это получить 5 >= res
. Если вы создадите экземпляр квантификатора с 5
для x
, вы получите
5 >= 4 && 5 >= 4 ==> 5 >= res
, который упрощается до 5 >= res
, что вам нужно, так что это конец вашего доказательства.
Таким образом, доказательство сводится к созданию экземпляра квантификатора с 5
для x
. Далее вам нужно немного узнать о том, как верификатор Dafny создает квантификаторы. По сути, он делает это, просматривая «форму» квантификатора и ища похожие вещи в контексте того, что вы пытаетесь доказать. Под «формой» я подразумеваю такие вещи, как «функции и предикаты, которые он использует». Обычно этот метод работает хорошо, но в вашем случае квантификатор настолько прост, что не имеет никакой «формы», о которой можно было бы говорить. Следовательно, верификатор не может найти необходимое создание экземпляра.
Было бы хорошо, если бы мы могли просто сказать «эй, попробуйте создать экземпляр этого количественного выражения с помощью 5
для x
». Ну, мы можем, если мы дадим квантификатору некоторую «форму», к которой мы можем обратиться. Вот что пытаются сказать вики и другие руководства. Здесь полезно ввести предикат greater
. (Не пытайтесь писать аннотации триггера вручную.)
Хорошо, после введения greater
ваша спецификация говорит:
ensures greater(max, a, b)
ensures forall x :: greater(x, a, b) ==> x >= max
Это говорит "max
удовлетворяет greater(max, a, b)
" и «среди всех значений x
, которые удовлетворяют greater(x, a, b)
, max
является наименьшим». После вызова Max
в Main
у нас тогда будет:
greater(res, 4, 5)
forall x :: greater(x, 4, 5) ==> x >= res
Напомним, я сказал, что верификатор пытается выяснить, как создаются кванторы, просматривая квантификатор и просматривая контекст вокруг вашего утверждения. и вы пытаетесь создать экземпляр квантификатора с 5
для x
. Итак, если вы можете добавить что-то в контекст непосредственно перед утверждением, которое побуждает верификатора выполнить это создание, тогда все готово.
Вот ответ: вы хотите ввести термин greater(5, 4, 5)
. Это имеет форму, очень похожую на greater(x, 4, 5)
в квантификаторе. Из-за этого сходства верификатор будет создавать экземпляр x
с 5
, что дает
greater(5, 4, 5) ==> 5 >= res
И поскольку greater(5, 4, 5)
легко доказывается как true
, следует необходимый факт 5 >= res
.
Итак, измените тело Main
на
var res := Max(4, 5);
assert greater(5, 4, 5);
assert res == 5;
и все готово. Верификатор докажет оба утверждения. Первое тривиально, и после его подтверждения верификатор может использовать термин greater(5, 4, 5)
в доказательстве второго утверждения. Именно этот термин вызывает квантификатор, который выдает факт 5 >= res
, который подтверждает второе утверждение.
Я хочу отметить, что большинство кванторов, которые мы пытаемся доказать do , имеют некоторую форму уже. В вашем случае предикат greater
был введен для того, чтобы придать квантификатору некоторую форму. Техника добавления дополнительного утверждения (здесь assert greater(5, 4, 5)
) остается той же самой, независимо от того, был ли greater
уже определен или был введен как тривиальный предикат, обеспечивающий форму.