В настоящее время я использую Z3py для вывода некоторых инвариантов, которые кодируются как совокупность роговых предложений, в то же время предоставляя шаблон для инварианта. Сначала я начинаю с простого примера, если вы видите фрагмент кода ниже.Инвариантная индукция над роговыми предложениями с Z3py
x = 0;
while(x < 5){
x += 1
}
assert(x == 5)
Это приводит к роговых положений
х = 0 => Inv (х)
< х 5/\ Inv (х) => Inv (х + 1)
Не (х < 5)/\ Inv (х) => х = 5
инвариант здесь х < = 5.
Я предоставил шаблон для инварианта формы a * x + b < = c , так что все решатели должны угадать набор значений для a, b и c, которые могут уменьшиться до x < = 5 .
Однако, когда я кодирую его, я все время становлюсь неустойчивым. Если попытаться утвердить Not (x == 5), я получу a = 2, b = 1/8 и c = 2, что не имеет для меня никакого смысла в качестве контрпримера.
Я предоставляю свой код ниже и был бы благодарен за помощь в исправлении моей кодировки.
x = Real('x')
x_2 = Real('x_2')
a = Real('a')
b = Real('b')
c = Real('c')
s = Solver()
s.add(ForAll([x],And(
Implies(x == 0 , a*x + b <= c),
Implies(And(x_2 == x + 1, x < 5, a*x + b <= c), a*x_2 + b <= c),
Implies(And(a*x + b <= c, Not(x < 5)), x==5)
)))
if (s.check() == sat):
print(s.model())
Редактировать: он становится для меня незнакомцем. Если я удалю определение x_2 и просто замените x_2 на (x + 1) во втором предложении horn, а также удалю x_2 = x_2 + 1, я получаю unsat ли я пишу Not (x == 5) или x == 5 в заключительном пункте рога.
Думаю, я исправил его. Я изменил все Reals на Ints и удалил определение x_2, как описано в моем редактировании. Внезапно он работает, и я получаю правильный инвариант x <= 5. Тем не менее, я немного смущен результатами, которые я получил при использовании Reals, поэтому был бы благодарен за любое объяснение, которое может предложить кто-то, который описывает мне проблему с Reals. – wrahman