Anwendungen von Logik SMT-Solver (Satisfiability modulo theories) 1 Beispiel: Verwendung eines SMT Solvers in Java 2 SMT Grundlagen 3 Beispiel: Programm-Verifikation 4 Grundlagen der Programm-Verifikation: Von Programmen zu Logik A. Poetzsch-Heffter (TU Kaiserslautern) Logik SoSe 2017 1 / 34 SMT-Solver Definition 1.1 (Satisfiability modulo theories) Seien T1 , . . . , Tn Theorien erster Stufe mit jeweils unterschiedlichen Funktions- und Prädikats-Symbolen und A eine Formel über eine Signatur mit den Symbolen aus den Theorien. Dann ist die Frage, ob T1 ∪ · · · ∪ Tn ∪ {A} erfüllbar ist, das Problem der Erfüllbarkeit modulo Theorien T1 , . . . , Tn . Definition 1.2 (SMT-Solver) Ein SMT-Solver für Theorien T1 , . . . , Tn ist ein Programm, welches eine Formel A nimmt und prüft, ob diese zusammen mit den eingebauten Theorien T1 , . . . , Tn erfüllbar ist. Der SMT-Solver muss nicht für jede Eingabe ein Ergebnis liefern. Das Problem ist im Allgemeinen unentscheidbar. A. Poetzsch-Heffter (TU Kaiserslautern) Logik SoSe 2017 2 / 34 Z3 SMT-Solver Z3 ist ein SMT-Solver. Entwickelt von Microsoft Research (Leonardo de Moura, Nikolaj Bjørner). Unterstützte Theorien: Arrays Bit-Vectors Integer Arithmetic Real Arithmetic mixed Integer Real Arithmetic Integer Difference Logic Rational Difference Logic ... Z3 verwendet eine Logik mit Typen (Sorten). A. Poetzsch-Heffter (TU Kaiserslautern) Logik SoSe 2017 3 / 34 Beispiel Theorie: Ganze Zahlen mit üblichen Operatoren A ≡ x > 5 ∧ ¬(x > 3) ∨ y > 2 ∧ ¬(x + y > 8) A. Poetzsch-Heffter (TU Kaiserslautern) Logik SoSe 2017 4 / 34 Z3 als Java-Bibliothek A ≡ x > 5 ∧ ¬(x > 3) ∨ y > 2 ∧ ¬(x + y > 8) Context c = new Context(cfg); IntExpr x = c.mkIntConst("x"); IntExpr y = c.mkIntConst("y"); // x > 5 BoolExpr p1 = c.mkGt(x, c.mkInt(5)); // x > 3 BoolExpr p2 = c.mkGt(x, c.mkInt(3)); // y > 2 BoolExpr p3 = c.mkGt(y, c.mkInt(2)); // x+y > 8 BoolExpr p4 = c.mkGt(c.mkAdd(x, y), c.mkInt(8)); // p1 && (!p2 || p3) && !p4 BoolExpr and = c.mkAnd( p1, c.mkOr(c.mkNot(p2), p3), c.mkNot(p4)); Solver s = c.mkSolver(); s.add(and); Status res = s.check(); A. Poetzsch-Heffter (TU Kaiserslautern) Logik SoSe 2017 5 / 34 Z3 Anwendung: Minesweeper KI Ziel: Alle sicheren Felder aufdecken. Verloren, wenn Miene aufgedeckt. Für aufgedeckte Felder: Anzeige, wie viele Mienen in den Nachbarfeldern sind. A. Poetzsch-Heffter (TU Kaiserslautern) Logik SoSe 2017 6 / 34 Minesweeper KI Zwei Funktionssymbole: m(x, y ): Anzahl der Mienen auf einem Feld. s(x, y ): Anzahl der Mienen in den Nachbarfeldern. Spielregeln als logische Formeln: 1 Auf jedem Feld ist entweder eine oder keine Miene. ∀x.∀y . m(x, y ) = 0 ∨ m(x, y ) = 1 2 Außerhalb des Spielfeldes sind keine Mienen. (Beispiel: 12 Zeilen, 22 Spalten) ∀x.∀y . (x < 0 ∨ x ≥ 22 ∨ y < 0 ∨ y ≥ 12) → m(x, y ) = 0 3 Zusammenhang zwischen m und s. ∀x.∀y . s(x, y ) = m(x − 1, y − 1) + m(x, y − 1) + m(x + 1, y − 1) + m(x − 1, y ) + m(x + 1, y ) + m(x − 1, y + 1) + m(x, y + 1) + m(x + 1, y + 1) A. Poetzsch-Heffter (TU Kaiserslautern) Logik SoSe 2017 7 / 34 Minesweeper KI 1 1 ? Frage: Ist Zelle unten rechts sicher? ? Γ, m(1, 0) = 0, s(1, 0) = 1, m(1, 1) = 0, s(1, 1) = 1 |= m(2, 2) = 0 Wobei Γ die Spielregeln der vorherigen Folie sind. Äquivalent: Ist n o Γ∪ m(1, 0) = 0, s(1, 0) = 1, m(1, 1) = 0, s(1, 1) = 1, ¬ m(2, 2) = 0 unerfüllbar? Diese Frage kann der SMT-Solver Z3 beantworten. A. Poetzsch-Heffter (TU Kaiserslautern) Logik SoSe 2017 8 / 34 Implementierung Java-Implementierung: https://github.com/peterzeller/java-simple-mine-sweeper Basierend auf Minesweeper-Implementierung von Syohei Yoshida: https://github.com/syohex/java-simple-mine-sweeper. Python Implementierung und weitere Anwendungen von Z3 (in Python): https://yurichev.com/writings/SAT_SMT_draft-EN.pdf https://github.com/dennis714/SAT_SMT_article/blob/master/SMT/ minesweeper/minesweeper_solver.py A. Poetzsch-Heffter (TU Kaiserslautern) Logik SoSe 2017 9 / 34 SMT Grundlagen: T-Conflict Ein Solver für eine Theorie stellt die Funktion T-Conflict bereit. Eingabe: Konjunktion von Literalen: L1 ∧ · · · ∧ Ln Ausgabe: Erfüllbar oder unerfüllbar? (oder “unknown”) Falls unerfüllbar: unerfüllbare Teilmenge (möglichst klein) Beispiel: x > 0 ∧ x + y > 10 ∧ 2 ∗ x < y ∧ y ≤ 6 Nicht erfüllbar, es muss gelten: ¬(x + y > 10) ∨ ¬(2 ∗ x < y ) ∨ ¬(y ≤ 6) A. Poetzsch-Heffter (TU Kaiserslautern) Logik SoSe 2017 10 / 34 Kombination mit Davis-Putnam-Algorithmen x > 5 ∧ ¬(x > 3) ∨ y > 2 ∧ ¬(x + y > 8) p1 ∧ ( ¬p2 ∨ p3 ) ∧ ¬p4 p1 := 1 (¬p2 ∨ p3 ) ∧ ¬p4 p2 := 0 ¬p4 p4 := 0 1 Anfrage an Theory-Solver: p1 ∧ ¬p2 ∧ ¬p4 erfüllbar? Antwort: Nein, es muss ¬p1 ∨ p2 gelten. A. Poetzsch-Heffter (TU Kaiserslautern) Logik SoSe 2017 11 / 34 Kombination mit Davis-Putnam-Algorithmen (Iteration 2) x > 5 ∧ ¬(x > 3) ∨ y > 2 ∧ ¬(x + y > 8) p1 ∧ (¬p2 ∨ p3 ) ∧ ¬p4 ∧ (¬p1 ∨ p2 ) Theorie-Lemma wird hinzugefügt. p1 := 1 (¬p2 ∨ p3 ) ∧ ¬p4 ∧ p2 p2 := 1 Anfrage an Theory-Solver: p1 ∧ p2 ∧ p3 ∧ ¬p4 erfüllbar? p3 ∧ ¬p4 p3 := 1 ¬p4 Antwort: Nein, es muss gelten: ¬p1 ∨ ¬p3 ∨ p4 p4 := 0 1 A. Poetzsch-Heffter (TU Kaiserslautern) Logik SoSe 2017 12 / 34 Kombination mit Davis-Putnam-Algorithmen (Iteration 3) x > 5 ∧ ¬(x > 3) ∨ y > 2 ∧ ¬(x + y > 8) p1 ∧ (¬p2 ∨ p3 ) ∧ ¬p4 ∧ (¬p1 ∨ p2 ) ∧ (¬p1 ∨ ¬p3 ∨ p4 ) p1 := 1 (¬p2 ∨ p3 ) ∧ ¬p4 ∧ p2 ∧ (¬p3 ∨ p4 ) A. Poetzsch-Heffter (TU Kaiserslautern) p2 := 1 p3 ∧ ¬p4 ∧ (¬p3 ∨ p4 ) p3 := 1 ¬p4 ∨ p4 p4 := 0 0 Formel unerfüllbar! Logik SoSe 2017 13 / 34 Verfahren Für eine Formel ohne Quantoren in KNF Form: Betrachte Literale und verwende aussagenlogischen Erfüllbarkeits-Check. Wenn Formel aussagenlogisch unerfüllbar, dann fertig. Falls erfüllende Belegung gefunden, Anfrage an Theorie-Solver. Falls erfüllbar in Theorie: Formel erfüllbar. Andernfalls füge Theorie-Lemma von Theorie-Solver zur Formel hinzu. Terminierung: Menge der Literale ist endlich ⇒ Menge der erzeugten Klauseln endlich. ⇒ Wenn Theorie-Solver immer terminiert, dann terminiert das Verfahren. A. Poetzsch-Heffter (TU Kaiserslautern) Logik SoSe 2017 14 / 34 Weiterführende Mechanismen Für einen SMT-Solver sind in der Praxis noch weitere Mechanismen notwendig. Davis–Putnam–Logemann–Loveland (DPLL) Algorithmus (Weiterentwicklung des Davis-Putnam-Verfahrens aus der Vorlesung) Früheres Aufrufen des Theorie-Solvers. T-Propagation: Wenn bereits Bewertung für Literale L1 . . . Ln gewählt wurde und Literal L in der Formel vorkommt und T ∪ {L1 , . . . , Ln } |= L, dann kann L gewählt werden (kein Anwenden der Split-Regel nötig). Formeln umschreiben, sodass ein Literal jeweils nur die Signatur einer Theorie verwendet. (Verknüpfung durch Gleichheits-Einschränkungen) ... A. Poetzsch-Heffter (TU Kaiserslautern) Logik SoSe 2017 15 / 34 Quantoren ∃-Quantoren durch Skolemisierung eliminieren. ∀-Quantoren intelligent instantiieren. I I I Heuristiken: Beispiel: Für Formel ∀x. A, wähle Term t, so dass A{x/t} viele bereits bekannte Terme enthält. Hilfe von Benutzer durch Angabe von Triggern. Superposition Calculus: Verallgemeinerung der prädikatenlogischen Resolution zu Formeln mit Gleichheit A. Poetzsch-Heffter (TU Kaiserslautern) Logik SoSe 2017 16 / 34 Zusammenfassung: SMT-Solver Kombination von Logik mit praktischen Algorithmen für bestimmte Theorien. Intern: Verwendet Weiterentwicklung von Davis-Putnam und Resolution. Können als allgemeiner Algorithmus verwendet werden um Probleme zu lösen. Insbesondere: Probleme aus NP. Überwiegende Anwendung: Programmanalyse, Programmverifikation A. Poetzsch-Heffter (TU Kaiserslautern) Logik SoSe 2017 17 / 34 Programm-Verifikation Vor dem Ausführen eines Programms (⇒ statisch) Prüfen, ob ein Programm bestimmte Eigenschaften hat. Beispielsweise: I I I I Das Programm wirft keine Nullpointer-Exceptions Das Programm terminiert für alle Eingaben. Das Programm verbraucht nie mehr als 100MB Arbeitsspeicher. Die Methode m verhält sich für alle gültigen Eingaben wie spezifiziert. Tool-Support notwendig (von Hand zu aufwendig und zu unzuverlässig) A. Poetzsch-Heffter (TU Kaiserslautern) Logik SoSe 2017 18 / 34 Beispiel: Dafny Dafny ist eine Programmiersprache mit Unterstützung für Spezifikation. Der Dafny Static-Program-Verifier ist ein Tool um funktionale Korrektheits-Eigenschaften eines Dafny-Programms zu verifizieren. Entwickelt von Microsoft Research (Rustan Leino). A. Poetzsch-Heffter (TU Kaiserslautern) Logik SoSe 2017 19 / 34 Dafny Beispiel: Minimum von 3 Zahlen 1 2 3 4 5 6 7 8 9 10 11 12 13 method min(x: int, y: int, z: int) returns (r: int) ensures r <= x; ensures r <= y; ensures r <= z; { if (x < y && x < z) { r := x; } else if (y < x && y < z) { r := y; } else { r := z; } } $ Dafny.exe min.dfy min.dfy(10,11): Error BP5003: A postcondition might not hold on this return path. min.dfy(2,10): Related location: This is the postcondition that might not hold. http://rise4fun.com/Dafny/y7D5 A. Poetzsch-Heffter (TU Kaiserslautern) Logik SoSe 2017 20 / 34 Dafny Beispiel: Minimum aus Array 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 method min(ar: array<int>) returns (min: requires ar != null; requires ar.Length > 0; ensures forall i :: 0 <= i < ar.Length ensures exists i :: 0 <= i < ar.Length { min := ar[0]; var pos := 1; while (pos < ar.Length) decreases ar.Length - pos; invariant pos <= ar.Length; invariant forall i :: 0 <= i < pos invariant exists i :: 0 <= i < pos { if (ar[pos] < min) { min := ar[pos]; } pos := pos + 1; } } int) ==> min <= ar[i]; && ar[i] == min; ==> min <= ar[i]; && ar[i] == min; http://rise4fun.com/Dafny/s7BI A. Poetzsch-Heffter (TU Kaiserslautern) Logik SoSe 2017 21 / 34 Begriffsklärung: Vor-, Nachbedingung Prozedureigenschaften lassen sich durch Vor- und Nachbedingungen beschreiben: Die Vorbedingung formuliert Anforderungen an den Vorzustand; wenn die Vorbedingung gilt, muss die Prozedur ohne Fehler terminieren. Die Nachbedingung formuliert die Eigenschaften des Nachzustands → in Abhängigkeit vom Vorzustand (z.B. Parameterwerte); → unter der Voraussetzung, dass beim Aufruf die Vorbedingung gilt. A. Poetzsch-Heffter (TU Kaiserslautern) Logik SoSe 2017 22 / 34 Begriffsklärung: Prozedurspezifikation Eine Prozedurspezifikation besteht aus: einer Vorbedingung: requires <Ausdruck> einer Variablenliste: modifies <Liste von Variablen> einer Nachbedingung: ensures <Ausdruck> Eine Prozedur darf nur die globalen Variablen und referenzierten Objekte / Arrays verändern, die in der Variablenliste aufgeführt sind. A. Poetzsch-Heffter (TU Kaiserslautern) Logik SoSe 2017 23 / 34 Partielle Korrektheit Definition 1.3 (Partielle Korrektheit) Wenn c eine Anweisung mit Vorbedingung P und Nachbedingung Q ist, dann nennen wir c partiell korrekt, wenn für alle Programm-Zustände s1 mit P(s1 ) gilt: Wenn die Ausführungen von Anweisung c startend im Zustand s1 in einem Zustand s2 enden kann, dann gilt Q(s1 , s2 ). Formal: ∀s1 , s2 . exec(c, s1 , s2 ) ∧ P(s1 ) → Q(s2 ) Wobei exec(c, s1 , s2 ) heißt, dass das Ausführen von Anweisung c in Zustand s1 in Zustand s2 enden kann. A. Poetzsch-Heffter (TU Kaiserslautern) Logik SoSe 2017 24 / 34 Totale Korrektheit Definition 1.4 (Totale Korrektheit) Wenn c eine Anweisung mit Vorbedingung P und Nachbedingung Q ist, dann nennen wir c (total) korrekt, wenn für alle Programm-Zustände s1 mit P(s1 ) gilt: Wenn die Anweisung c im Zustand s1 ausgeführt wird, dann terminiert die Ausführung in einem Zustand s2 für den gilt Q(s1 , s2 ). Formal: ∀s1 , s2 . P(s1 ) → (terminates(c, s1 ) ∧ ∀s2 . exec(c, s1 , s2 ) → Q(s2 )) Wobei exec(c, s1 , s2 ) wie zuvor definiert ist und terminates(c, s1 ) aussagt, dass die Ausführung von c im Zustand s1 immer terminiert. A. Poetzsch-Heffter (TU Kaiserslautern) Logik SoSe 2017 25 / 34 Von Programm und Spezifikation zu logischer Formel Idee: Schwächste Vorbedingung (engl.: weakest precondition) berechnen: Berechne aus Nachbedingung und Anweisung, was als Vorbedingung notwendig ist. Prüfe dann, ob die spezifizierte Vorbedingung die tatsächliche impliziert. ⇒ SMT-Solver verwenden (Dafny verwendet Z3) Notation: Für eine Anweisung c und Nachbedingung Q ist wp(c, Q) die schwächste Vorbedingung, so dass c korrekt ist. A. Poetzsch-Heffter (TU Kaiserslautern) Logik SoSe 2017 26 / 34 wp: Zuweisungen Zuweisung: wp(x := E , Q) = Q{x/E } Beispiele: wp(x := 2 ∗ y , (x > 0 ∧ x < 10)) = (2 ∗ y > 0 ∧ 2 ∗ y < 10) wp(x := x + 1, x > 0) = x + 1 > 0 Einige Aspekte wurden hier ignoriert: Bei der Substitution muss eventuell der Ausdruck E in die Logik übersetzt werden. Außerdem haben Ausdrücke eventuell auch Vorbedingungen, wie zum Beispiel, dass der Index bei einem Array-Zugriff im gültigen Bereich ist. A. Poetzsch-Heffter (TU Kaiserslautern) Logik SoSe 2017 27 / 34 wp: Sequenz von Anweisungen wp(c1 ; c2 , Q) = wp(c1 , wp(c2 , Q)) Beispiel: wp(t := a; a := b; b := t, a = bold ∧ b = aold ) = wp(t := a, wp(a := b; b := t, a = bold ∧ b = aold )) = wp(t := a, wp(a := b, wp(b := t, a = bold ∧ b = aold ))) = wp(t := a, wp(a := b, a = bold ∧ t = aold )) = wp(t := a, b = bold ∧ t = aold ) = (b = bold ∧ a = aold ) A. Poetzsch-Heffter (TU Kaiserslautern) Logik SoSe 2017 28 / 34 Notation: Assertions für Zwischenschritte 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class C { var a: int; var b: int; method swap() modifies this; ensures a == old(b) && b == old(a); { var t: int; assert b t := a; assert b a := b; assert a b := t; assert a == old(b) && a == old(a); == old(b) && t == old(a); == old(b) && t == old(a); == old(b) && b == old(a); } } http://rise4fun.com/Dafny/dIILF A. Poetzsch-Heffter (TU Kaiserslautern) Logik SoSe 2017 29 / 34 Dafny Beispiel: Binärsuche 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 method binarysearch(x: int, ar: array<int>) returns (result: int) requires sorted(ar); ensures result >= 0 ==> result < ar.Length && ar[result] == x; ensures (exists i: int :: i>= 0 && i<ar.Length && ar[i] == x) <==> (result >= 0); { var start := 0; var end := ar.Length - 1; while (end >= start) { var mid := start + (end - start)/2; if (x < ar[mid]) { end := mid - 1; } else if (x > ar[mid]) { start := mid + 1; } else { result := mid; return; } } result := -1; } A. Poetzsch-Heffter (TU Kaiserslautern) Logik SoSe 2017 30 / 34 Dafny Beispiel: Binärsuche Zur Verifikation in Dafny werden Annotationen benötigt: ... while (end >= start) decreases 1 + end - start; invariant start >= 0; invariant end < ar.Length; invariant end >= start-1; invariant forall i: int :: i>= 0 && i<ar.Length && ar[i] == x ==> start <= i && i <= end; { ... Schleifen-Invariante (invariant) Maß für Terminierung (decreases) http://rise4fun.com/Dafny/Re4T A. Poetzsch-Heffter (TU Kaiserslautern) Logik SoSe 2017 31 / 34 Seminar WS 17/18 Themen: SMT solvers Generating verification conditions The Dafny and Boogie verification tools Property based testing Concolic testing Mehr Informationen: https://softech.cs.uni-kl.de/homepage/de/teaching/WS17/seminar/ A. Poetzsch-Heffter (TU Kaiserslautern) Logik SoSe 2017 32 / 34 Material Leonardo Mendonça de Moura, Nikolaj Bjørner: Satisfiability Modulo Theories: Introduction and Applications. Z3 SMT solver https://github.com/Z3Prover/z3 Dafny Verfification tool https://github.com/Microsoft/dafny A. Poetzsch-Heffter (TU Kaiserslautern) Logik SoSe 2017 33 / 34 Klausur Abschlussklausur: 11. September Lernraum: 28. August bis 8. September Teilweise mit Ansprechpartner (Zeiten werden noch angekündigt) Altklausuren von Prof. Meyer und Prof. Madlener im KAI Gleiche Regeln wie bei Zwischenklausur: I Ein DIN A4 Blatt mit eigenen, handschriftlichen Notizen (beidseitig) erlaubt A. Poetzsch-Heffter (TU Kaiserslautern) Logik SoSe 2017 34 / 34