Ich verwende Z3py, um einige Invarianten abzuleiten, die als eine Konjunktion von Hornsätzen kodiert sind, während sie auch eine Vorlage für die Invariante liefern. Ich fange zuerst mit einem einfachen Beispiel an, wenn Sie das Code-Snippet unten sehen.Invariante Induktion über Hornsätze mit Z3py
x = 0;
while(x < 5){
x += 1
}
assert(x == 5)
Dies schlägt sich in den Horn-Klauseln
x = 0 => Inv (x)
x < 5/\ Inv (x) => Inv (x +1)
Nicht (x < 5)/\ Inv (x) => x = 5
Die hier unveränderlich ist x < = 5.
Ich habe eine Vorlage für die Invariante der Form a * x + b < = c zur Verfügung gestellt, so dass der Löser nur eine Menge von Werten für a, b und c erraten muss, die auf x < = 5 reduziert werden kann
Aber wenn ich es kodiere, werde ich immer ungeeignet. Wenn ich versuche, Nicht (x == 5) zu bestätigen, bekomme ich a = 2, b = 1/8 und c = 2, was für mich als Gegenbeispiel wenig Sinn macht.
Ich stelle meinen Code zur Verfügung und wäre dankbar für jede Hilfe bei der Korrektur meiner Codierung.
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())
Edit: es wird für mich Fremder. Wenn ich die x_2-Definition entferne und einfach x_2 durch (x + 1) in der zweiten horn-Klausel ersetze sowie x_2 = x_2 + 1 lösche, werde ich ungeeignet, ob ich Not (x == 5) oder x == 5 schreibe in der letzten Hornklausel.
Ich denke, ich habe es behoben. Ich änderte alle Reals zu Ints und löschte die x_2-Definition wie in meiner Bearbeitung beschrieben. Plötzlich funktioniert es und ich bekomme die richtige Invariante von x <= 5. Nichtsdestotrotz bin ich ein wenig verwirrt über die Ergebnisse, die ich bei der Verwendung von Reals bekommen habe, also wäre ich dankbar für jede Erklärung, die jemand anbieten kann, die mir das Problem mit Reals beschreibt. – wrahman