Effizientes Model-Checking f ur CTL
←
→
Transkription von Seiteninhalten
Wenn Ihr Browser die Seite nicht korrekt rendert, bitte, lesen Sie den Inhalt der Seite unten
Effizientes Model-Checking für CTL Diplomarbeit im Studiengang Mathematik mit Studienrichtung Informatik Julia Gerock Mtr.-Nr. 2294990 Institut für Theoretische Informatik Fakultät für Elektrotechnik und Informatik Leibniz Universität Hannover Prüfer: Prof. Dr. Heribert Vollmer Zweitprüfer: Prof. Dr. Rainer Parchmann Betreuer: M. Sc. Arne Meier 26. Oktober 2009
Danksagung Ich bedanke mich ganz herzlich bei Herrn Arne Meier für die hervorragende Betreuung und Unterstützung meiner Diplomarbeit.
Inhaltsverzeichnis 1 Einführung 1 1.1 Motivation und Aufgabenstellung . . . . . . . . . . . . . . . . . . . . . . . . 1 1.2 Gliederung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 2 Theoretische Grundlagen 3 2.1 Model-Checking-Prozess . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2.2 Kripke-Struktur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 2.3 CTL als eine von temporalen Logiken . . . . . . . . . . . . . . . . . . . . . . 5 2.4 Beispiel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 2.5 Komplexitätstheorie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 3 Model-Checking für CTL 13 3.1 Formulierung des Problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 3.2 Komplexität des Model-Checking-Problems für CTL . . . . . . . . . . . . . 14 3.3 Model-Checking für CTL und CTLpos . . . . . . . . . . . . . . . . . . . . . 15 3.3.1 CTL-MC(ALL) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 3.3.2 CTLpos -MC(EX, EG, EU, ER) . . . . . . . . . . . . . . . . . . . . 17 4 Design und Implementierung 21 4.1 Basisprogramm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 4.2 Neue Klassenstruktur und die Implementierungsaspekte . . . . . . . . . . 22 4.3 Bedienungsanleitung zum Programm . . . . . . . . . . . . . . . . . . . . . . 30 5 Auswertung von Algorithmen 36 5.1 Allgemeine Beschreibung der Experimente . . . . . . . . . . . . . . . . . . . 36 5.1.1 Testsystem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 5.1.2 Testdaten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 5.1.3 Ablauf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 5.2 Zwei Implementierungen des CTLpos -Algorithmus . . . . . . . . . . . . . . 38 5.3 Auswertung von CTLpos - und CTL-Algorithmen . . . . . . . . . . . . . . . 40 5.4 Laufzeit des CTL-Algorithmus für Kripke-Strukturen mit bis zu 300 Zu- ständen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 6 Zusammenfassung und Ausblick 48 Literaturverzeichnis 54
1 Einführung 1.1 Motivation und Aufgabenstellung Heutzutage werden Software- und Hardware-Systeme so gut wie in jedem Gebiet ein- gesetzt und haben sich in unserem Leben fest etabliert. Somit wird die Abhängigkeit von der Zuverlässigkeit dieser Systeme immer größer. Andererseits wird es schwieriger, die Funktionsweise fehlerfrei zu gewährleisten, da sich der Umfang und die Komplexität der Systeme auch ständig steigern. Mithilfe der Standardmittel wie Testen oder Simu- lation werden Fehlerfälle oft unvollständig abgedeckt. Und sogar bei einer vollständigen Abdeckung kann das System weitere Fehler enthalten, die nicht entdeckt wurden. Deswegen ist die Notwendigkeit entstanden, neue, möglichst effiziente Methoden zu entwickeln, um mit deren Hilfe die Korrektheit und somit die Qualität eines Systems zu sichern und beweisen zu können. Dies kann ermöglicht werden, indem ein zu entwi- ckelndes System sowie dessen relevante Eigenschaften formalisiert werden, und es durch Verifikation überprüft wird, ob die gewünschten Eigenschaften im System erfüllt sind. Model-Checking als eine dieser Methoden basiert auf diesem Prinzip. Dabei werden ein Modell M , als eine Beschreibung des Systems, und eine logische Formel ϕ, als eine Spezifikation des Systems, verifiziert (M ⊧ ϕ). Je nach der Art der Formeln1 werden diverse Klassen von Model-Checking-Problemen unterschieden. Diese Arbeit befasst sich mit dem Model-Checking-Problem für CTL (Computation Tree Logic). Ziel der Arbeit besteht darin, dieses Problem in Bezug auf seine Effizienz auszuarbei- ten. Als Basis werden die im Institut für Theoretische Informatik der Leibniz Universität Hannover entstandenen Ergebnisse der Forschung des Model-Checking-Problems ver- wendet, die weiter unten dargestellt sind. Das Model-Checking-Problem für CTL ist als P-vollständig bekannt. Zugehörigkeit eines Problems zu einer Komplexitätsklasse kann durch Angeben eines Algorithmus bewiesen werden, der dieses Problem entscheidet und selbst in dieser Komplexitätsklasse liegt. Ein weiteres Ziel der Arbeit ist es, diverse Al- gorithmen des Model-Checking-Problems für CTL vorzustellen, zu implementieren und ihre Effizienz zu vergleichen. 1 In Abhängigkeit davon, welche Operatoren erlaubt bzw. welche Constraints festgelegt sind (z. B. CTL, CTL*, LTL). 1
1 Einführung 1.2 Gliederung In der vorliegenden Arbeit wird nach der Einleitung in Kapitel 2 auf theoretische Grundlagen eingegangen. Hier werden wichtige Grundbegriffe definiert, die für diese Ar- beit benötigt werden. Danach wird ein Beispiel präsentiert, um ein intuitives Verständnis zu schaffen. Kapitel 3 bildet den Hauptteil dieser Arbeit. Hier wird das Model-Checking-Problem für CTL konkretisiert. Dabei wird untersucht, mit welcher Effizienz dieses Problem gelöst werden kann und welche Schwierigkeiten sich dabei ergeben. In Abschnitt 3.3.1 wird das Model-Checking-Problem auf die gesamte Klasse CTL verallgemeinert und ein Al- gorithmus aus [CGP99] präsentiert, der in Polynomialzeit arbeitet. In Abschnitt 3.3.2 wird ein speziell definiertes Fragment CTLpos betrachtet. Für dieses wird hier ein weiterer Entscheidungsalgorithmus aus [BMT+ ] vorgestellt. In Kapitel 4 wird behandelt, wie die in Kapitel 3 geschilderten Algorithmen im- plementiert werden können. Diese werden als eine Erweiterung eines existierenden Pro- gramms ([Sol09]) realisiert. Das Programm wird hier auch kurz erläutert. In Kapitel 5 wird die Laufzeit der Algorithmen für CTL und CTLpos untersucht und verglichen. Experimente und deren Ergebnisse werden hier veranschaulicht. Kapitel 6 enthält eine Zusammenfassung und einen Ausblick der Diplomarbeit. 2
2 Theoretische Grundlagen In diesem Kapitel werden die für diese Arbeit relevanten Begriffe wie Model-Checking, Kripke-Struktur, temporale Logik und insbesondere CTL eingeführt und in Anlehnung an [CGP99] definiert. Diese werden anschließend mittels eines Beispiels verdeutlicht. Um die Effizienz des Model-Checking-Problems untersuchen zu können, werden auch die für dieses Thema wichtigsten Resultate der Komplexitätstheorie in diesem Kapitel zusammengefasst. 2.1 Model-Checking-Prozess Model-Checking ist als eine Verifikationsmethode von endlichen zustandsbasierten Sys- temen bekannt, die die Korrektheit eines Systems bezüglich seiner Spezifikation beweist oder widerlegt und dabei automatisch abläuft. Diese zwei vorteilhaften Aspekte unter- scheiden Model-Checking von den anderen Verifikationsverfahren (z. B. deduktive Verifi- kation) sowie von dem Testen und der Simulation erheblich (vgl. [Sch]). Der Begriff wurde in den 80 Jahren geprägt. Diese Methode ist bereits für den Korrektheitsnachweis beim Entwurf von komplexen sequentiellen Schaltungen und von Kommunikationsprotokollen erfolgreich praktisch eingesetzt worden (vgl. [CGP99]). Mit Hilfe des Model-Checkings können zur Zeit sowohl Hardware- als auch Software-Systeme untersucht werden. Im Allgemeinen gliedert sich das Model-Checking in drei Schritte: 1. Modellierung 2. Spezifizierung 3. Verifikation Im ersten Schritt muss ein zu analysierendes System S in eine vereinbarte Form ge- bracht werden. Somit wird ein Modell M des Systems S erzeugt. Hier ist es wichtig, relevante von nicht relevanten Eigenschaften des Systems zu trennen und nur die signifi- kanten, diese aber alle, abzubilden. Außerdem ist es zu entscheiden, ob das System zum Anwenden des Model-Checkings tauglich, d. h. zustandsbasiert und endlich (mit einem endlich repräsentierbaren Zustandsraum) ist. Dabei kann eine Zustandsexplosion ent- stehen. In den letzten zehn Jahren wurden aber erhebliche Fortschritte zur Behandlung dieses Problems erreicht (siehe [CGP99]). Es gibt mehrere Methoden, um ein System in ein Modell zu überführen. In dieser Arbeit erfolgt dies mittels Konstruierens einer Kripke-Struktur, die in Abschnitt 2.2 erläutert wird. 3
2 Theoretische Grundlagen In der Spezifikationsphase werden geforderte Eigenschaften des Systems S formal er- fasst. Somit entsteht eine Spezifikation als eine Menge von Regeln, die das System erfüllen muss. Bei der Erstellung der Spezifikation spielt ihre Vollständigkeit eine zentrale Rolle, da nur diejenigen Eigenschaften mit dem Modell verifiziert werden, die in der Spezifika- tion vorkommen. Wenn nicht alle relevanten Systemanforderungen in der Spezifikation abgebildet sind, werden sie bei der Verifikation nicht beachtet. Dies kann allerdings zu einer falschen Entscheidung führen, dass das Modell die Systemanforderungen erfüllt, obwohl das nicht vollständig geprüft wurde. Meistens wird temporale Logik als Spezifikationssprache von den Software- und Hard- ware-Systemen benutzt. Temporale Logik ermöglicht es, zeitliche Abläufe des Systems zu beschreiben. In diesem Fall wird die Spezifikation als eine Menge von temporal-logischen Formeln ϕ formuliert. Jede Formel drückt das nachzuweisende Verhalten des Systems über die Zeit aus. In Abschnitt 2.3 wird auf die temporale Logik genauer eingegangen. Im letzten Schritt werden spezielle Model-Checking-Algorithmen angewendet, um nachzuweisen oder zu widerlegen, dass das Modell M die Spezifikation ϕ erfüllt. Dieser Schritt erfolgt größtenteils automatisch, menschliche Teilnahme wird in der Praxis nur bei der Analyse der Verifikationsergebnisse gefordert. Das Model-Checking-Problem kann folgendermaßen formuliert werden. Sei S ein zu analysierendes System. Eingabe: ein Modell M des Systems S eine nachzuweisende Eigenschaft ϕ, die das System S haben muss Frage: Erfüllt das Modell M die Spezifikation ϕ?“ ” (M ⊧ ϕ?) Eine genauere Definition für das für die vorliegende Arbeit auszuarbeitende Model- Checking-Problem für CTL wird in Abschnitt 3.1 gegeben, nachdem die Begriffe Kripke- ” Struktur“ und CTL“ in den nächsten Abschnitten eingeführt werden. ” 2.2 Kripke-Struktur Zum Modellieren von endlichen zustandsbasierten Systemen werden beim Model-Che- cking Kripke-Strukturen verwendet. Diese ermöglichen, Eigenschaften eines Systems in verschiedenen Zuständen zu beschreiben, indem bestimmte Aussagen über das System den Zuständen zugeordnet werden. Beispielsweise ist eine Ampel (ein System) in einem Zustand rot“, und dabei wird ein Tonsignal“ abgegeben. In diesem Fall wird dieser ” ” Zustand beim Modellieren der Ampel mit den beiden Aussagen rot“ und Tonsignal“ ” ” markiert. Eine Kripke-Struktur ist wie folgt definiert (vgl. [CGP99], [BMT+ ]). 4
2 Theoretische Grundlagen Definition 2.2.1 (Kripke-Struktur) Sei AP eine Menge der atomaren Aussagen (atomic propositions). Eine Kripke-Struktur K über AP ist ein 4-Tupel K = (W, W0 , R, η), wobei 1. W eine endliche Menge der Zustände ist; 2. W0 ⊆ W die Menge der Start-Zustände ist; 3. R ⊆ W × W eine totale Transitionsrelation ist, d. h. für jeden Zustand w ∈ W gibt es einen Zustand w’ ∈ W mit (w, w’) ∈ R; 4. η ∶ W → P(AP ) eine Beschriftungsfunktion (labelling function) ist, die jedem Zustand die Menge der atomaren Aussagen zuordnet, die in diesem Zustand erfüllt sind. Bemerkung: • Manchmal wird die Menge der Start-Zustände nicht explizit angegeben. In diesen Fällen wird W0 aus der Definition ausgelassen. • Üblicherweise wird die Menge der atomaren Aussagen AP im Hinblick auf die gewünschte Spezifikation konstruiert. (vgl. [Sch]) In Abschnitt 2.4 ist ein Beispiel zu finden, wie sich ein System als eine Kripke-Struktur gestalten lässt. 2.3 CTL als eine von temporalen Logiken Temporale Logik wurde als eine Erweiterung der Aussagenlogik mit dem Ziel definiert, zeitliche Änderungen beschreiben zu können. Die Zeit wird hier als Folge (oder später als Pfad) von Zuständen betrachtet. In diversen Zuständen können Aussagen verschiedene Wahrheitswerte annehmen. Temporale Logik ermöglicht es, für eine logische Aussage ϕ solche Beziehungen zu modellieren, wie z. B. ϕ gilt immer“, ϕ wird nie wahr“, ϕ wird ” ” ” zum nächsten Zeitpunkt gelten“ usw. Dies erfolgt mittels der sogenannten temporalen Operatoren. Um auszudrücken, dass eine Eigenschaft des Systems gelten muss bzw. kann, werden die Pfad-Quantoren A bzw. E verwendet. Temporale Operatoren und Pfad-Quantoren sind in den Tabellen 2.1 und 2.2 aufgelistet und erläutert. Temporale Logik wurde im Jahr 1977 in der Arbeit von A. Pnueli The Temporal Lo- ” gic of Programs“ als eine Formalisierungssprache für Spezifikation und Verifikation von vergleichbaren Programmen zum ersten Mal vorgestellt und hat sich als eine Spezifika- tionsmethode zur Erfassung von Systemanforderungen beim Model-Checking etabliert. 5
2 Theoretische Grundlagen Operator Syntax Bedeutung Semantik Beispielpfad F Fϕ in the ϕ gilt irgendwann ” f uture“ oder auf dem nachfol- eventually“ genden Pfad ” G Gϕ globally“ ϕ gilt in jedem Zu- ” oder al- stand auf dem Pfad ” ways“ X Xϕ next time“ ϕ gilt im nächsten ” Zustand U ϕUψ until“ ϕ gilt in jedem Zu- ” stand, bis der Zu- stand erreicht wird, in dem ψ wahr ist R ϕRψ release“ ψ gilt bis zu einem ” Zustand, in dem ϕ gilt oder für im- mer, wenn ϕ immer falsch ist Tabelle 2.1: Temporale Operatoren. ϕ, ψ sind temporal-logische Formeln Quantor Syntax Name Semantik A Aϕ Allquantor Für alle Pfade gilt ϕ E Eϕ Existenzquantor Es existiert ein Pfad, für den ϕ gilt Tabelle 2.2: Pfad-Quantoren In Abhängigkeit von verwendeten Operatoren und von deren Semantik werden folgen- de Klassen von temporalen Logiken unterschieden: LTL: Linear Temporal Logic betrachtet die Zeit als eine lineare Abfolge von Zeitpunkten bzw. Zuständen CTL: Computational Tree Logic charakterisiert die Zeit als ein verzweigender Ablauf von Zuständen CTL*: Extended Computation Tree Logic. CTL* ⊃ LTL ∪ CTL. Ausdruckskraft von CTL*, CTL und LTL ist nicht vergleichbar, da sich nicht jede in einer Logik formulierte 6
2 Theoretische Grundlagen Aussage in eine äquivalente Aussage in der anderen Logik transformieren lässt. Beispiele dazu sind in [CGP99], [Sol09] zu finden. Da das Model-Checking-Problem für diese Arbeit auf CTL eingeschränkt ist, wird diese Logik hier genauer betrachtet. CTL wurde von Emerson und Clarke eingeführt. Wie die anderen temporalen Logiken beinhaltet sie folgende Bausteine: • atomare Aussagen • boolesche Operatoren ¬(NOT), ∧(AND) und ∨(OR) • temporale Operatoren F, G, X, U, R • Pfad-Quantoren A, E Die Sprache, die aus diesen Operatoren und Quantoren besteht, heißt CTL*. Aus diesen Komponenten werden CTL*-Formeln gestaltet. CTL* ist in [CGP99] und [Sol09] ausführlich beschrieben. Eine CTL-Formel ist eine CTL*-Formel mit einer Einschränkung auf die Verwendung von temporalen Operatoren und Pfad-Quantoren. Jeder temporale Operator darf nur nach einem Pfad-Quantor auftreten, und jeder Pfad-Quantor darf nur gefolgt von einem temporalen Operator in den CTL-Formeln vorkommen. Die Operatoren AF, AG, AX, AU, AR werden universale Operatoren genannt, EF, EG, EX, EU, ER heißen exis- tenzielle Operatoren. Universale und existenzielle Operatoren bilden die Menge ALL von allen CTL-Operatoren. Weiter wird eine CTL-Formel induktiv definiert. Definition 2.3.1 (CTL-Formel) Sei AP eine Menge von atomaren Aussagen, Q ∈ {A, E}. Die Symbole ⊺ und repräsentieren die Wahrheitswerte wahr“ und falsch“. ” ” • ⊺, sind CTL-Formeln. • Ist p ∈ AP , so ist p eine CTL-Formel. • Sind ϕ, ψ CTL-Formeln, dann sind (ϕ), ¬ϕ, ϕ ∧ ψ, ϕ ∨ ψ, QF ϕ, QG ϕ, QX ϕ, Q(ϕ U ψ), Q(ϕ R ψ) auch CTL-Formeln. Man unterscheidet zwei Arten von Formeln: Zustand- und Pfad-Formeln. Zustand- Formeln beschreiben Eigenschaften, die in einem Zustand gelten, und Pfad-Formeln charakterisieren Eigenschaften entlang eines Pfades. Definition 2.3.2 (Zustand-Formel) • ⊺, sind Zustand-Formeln. • Ist p ∈ AP , so ist p eine Zustand-Formel. • Sind ϕ, ψ Zustand-Formeln, dann sind (ϕ), ¬ϕ, ϕ ∧ ψ, ϕ ∨ ψ Zustand-Formeln. • Ist χ eine Pfad-Formel, so ist Aχ eine Zustand-Formel. 7
2 Theoretische Grundlagen Definition 2.3.3 (Pfad-Formel) • Ist ϕ eine Zustand-Formel, so ist ϕ auch eine Pfad-Formel. • Sind χ, π Pfad-Formeln, dann sind (χ), ¬χ, χ ∧ π, χ ∨ π, Xχ und χ U π Pfad- Formeln. Weiterhin ist {EX, EU, EG} eine minimale Menge der CTL-Operatoren, da jede CTL-Formel in eine äquivalente Formel konvertiert werden kann, in der nur die CTL- Operatoren EX, EU, EG sowie die booleschen Operatoren ¬ und ∨ verwendet werden. In der Tabelle 2.3 sind die entsprechenden Regeln aufgelistet. Regel № Allgemeine Form Konvertierte Form 1 Eϕ ¬A¬ϕ 2 ϕ∧ψ ¬(¬ϕ ∨ ¬ψ) 3 EF ϕ E(⊺ U ϕ) 4 E(ϕ R ψ) EG ψ∨ E (ψ U ¬(¬ϕ ∨ ¬ψ)) 5 AF ϕ ¬ EG(¬ϕ) 6 AX ϕ ¬ EX(¬ϕ) 7 AG ϕ ¬ EF(¬ϕ) 8 A(ϕ U ψ) ¬ (EG (¬ψ)∨ E (¬ψ U ¬(ϕ ∨ ψ))) 9 A(ϕ R ψ) ¬ E (¬ϕ U ¬ψ) Tabelle 2.3: Darstellung der CTL-Formeln durch die Operatoren EX, EU, EG, ¬, ∨ CTL, als eine CTL*-Logik, basiert auf der Kripke-Struktur. Um Systemanforderungen mittels CTL-Formeln zu spezifizieren, müssen diverse Eigenschaften des Systems in ver- schiedenen Zeitpunkten beschrieben werden. Die Zeitskala wird als Pfad von Zuständen in der das System repräsentierenden Kripke-Struktur interpretiert. Weiter wird ein Pfad definiert. Definition 2.3.4 (Pfad) Sei K = (W, W0 , R, η) eine Kripke-Struktur. Ein Pfad x in der Kripke-Struktur K ist eine unendliche Sequenz von Zuständen x = (x1 , x2 , ...) ∈ W ω , so dass (xi , xi+1 ) ∈ R ∀i ≥ 1. In Abschnitt 2.4 wird mittels eines Beispiels gezeigt, wie Systemanforderungen als CTL-Formeln erfasst werden können. 2.4 Beispiel Ein Model-Checking-Prozess kann in folgenden Schritten kurz gefasst werden. Sei S ein zu analysierendes System. 1. Modellierung: im ersten Schritt wird ein Modell M vom System S erstellt. M ist eine formale Beschreibung des Systems und spiegelt relevante Eigenschaften von S wider. Als Modellierungsmechanismus wird hier Kripke-Struktur eingesetzt. 8
2 Theoretische Grundlagen 2. Spezifizierung: hier werden Systemanforderungen Φ = {φj ∣ j = 0, 1, ...} erfasst. Für diese Arbeit sind solche Eigenschaften von Systemen relevant, die über verzweigen- de Zeit festgelegt werden sollen. Diese werden mittels CTL-Formeln formalisiert. 3. Verifikation: anschließend wird durch das Anwenden eines Algorithmus das Model- Checking-Problem entschieden, das folgendermaßen formuliert werden kann: Erfüllt das Modell M die Spezifikation Φ?“ ” An dieser Stelle wird ein Beispiel vorgestellt, mit dem gezeigt wird, wie Model-Checking angewendet werden kann. Es handelt sich um das bekannte Speisende Philosophen“-Problem (siehe Abbildung ” 2.1). 5 Philosophen A, B, C, D und E sitzen um einen Tisch. Es gibt fünf Teller mit dem Essen für jeden Philosophen, und zwischen je zwei Tellern liegt eine Gabel. Jeder denkt nach und isst abwechselnd. Zum Essen benötigen sie jeweils die beiden Gabeln neben sich. Es können somit maximal zwei Personen, die nicht nebeneinander sitzen, gleichzeitig speisen (vgl. [Har02]). Abbildung 2.1: Speisende Philosophen (vgl. [Sch]) Dieses Problem kann als ein zu analysierendes System S betrachtet werden. S kann mit Hilfe eines Graphen G (Abbildung 2.2) oder als eine entsprechende Kripke-Struktur K (Abbildung 2.3) modelliert und durch bestimmte Regeln (Systemanforderungen) ρj,j=0,1,... , die mittels temporal-logischer Formeln (hier CTL-Formeln) ϕj beschrieben werden, spe- zifiziert werden. Die Bezeichnungen der Zustände sind so gewählt, dass man erkennen kann, welche Philosophen in diesem Moment essen (bis auf den Ausnahmezustand S). Das heißt, im Zustand A isst der Philosoph A, im Zustand AC speisen die Philosophen A und C, im Zu- stand S in der Mitte denken alle Philosophen nach. Die Übergänge zwischen den Zustän- den stellen die Aktionen der Philosophen dar. Wenn ein Philosoph I ∈ {A, B, C, D, E} eine Gabel vom Tisch aufnimmt (pick up) bzw. zurückgibt (return), wird der entspre- chende Übergang mit Ip bzw. Ir beschriftet. Wenn man das System S in eine Kripke-Struktur K über AP überführt, ist sie wie folgt definiert und in Abbildung 2.3 dargestellt. 9
2 Theoretische Grundlagen Abbildung 2.2: Speisende Philosophen als ein Modell([Har02]) K = (W, {S}, R, η), wobei • AP = {a, b, c, d, e} die Menge der atomaren Aussagen ist, die den Namen der speisenden Philosophen entsprechen; • W = {S, A, B, C, D, E, AC, DA, DB, EB, EC} die Menge der Zustände ist; • R = {(S, A), (S, B), (S, C), (S, D), (S, E), (A, S), (B, S), (C, S), (D, S), (E, S), (A, AC), (A, DA), (B, EB), (B, DB), (C, AC), (C, EC), (D, DB), (D, DA), (E, EC), (E, EB), (EB, B), (EB, E), (AC, A), (AC, C), (DB, B), (DB, D), (EC, C), (EC, E), (DA, A), (DA, D)} die Transitionsrelation ist; • η ∶ W → P(AP ), für p ∈ AP, w ∈ W gilt: p ∈ η(w), falls der Philosoph mit dem Namen P ( groß p“) in dem Zustand w isst. Z. B. wenn der Philosoph A in dem ” Zustand w speist, dann ist a ∈ η(w). Das System S muss unter anderen z. B. folgende Eigenschaften erfüllen: • ρ0 = Die Philosophen A und B dürfen nie gleichzeitig essen.“ ” • ρ1 = Philosoph A isst als erster.“ ” • ρ2 = Wenn Philosoph D nichts gegessen hat, kann er irgendwann zusammen mit ” B etwas essen.“ 10
2 Theoretische Grundlagen Abbildung 2.3: Speisende Philosophen als eine Kripke-Struktur • ρ3 = Immer, wenn Philosoph D fertig gegessen hat, muss er solange nachdenken ” oder warten, bis Philosoph E auch etwas gegessen hat.“ Die entsprechenden CTL-Formeln sehen wie folgt aus: • ϕ0 = AG ¬(a ∧ b); • ϕ1 = A (¬(b ∨ c ∨ d ∨ e) U a); • ϕ2 = ¬d → EF(d ∧ b) = d ∨ EF(d ∧ b); • ϕ3 = AG(¬d → A(¬d U e)) = AG(d ∨ A(¬d U e)); Somit ist K ein Modell des Systems S und Φ = {ϕi ∣ i = 0, ..., 3} ist eine Spezifikation. Die Frage, ob das Modell K die Spezifikation Φ erfüllt, kann beantwortet werden, in- dem K und jede φ ∈ Φ verifiziert werden. Dies erfolgt mittels spezieller Model-Checking- Algorithmen, die in Kapitel 3 vorgestellt und erläutert werden. 11
2 Theoretische Grundlagen 2.5 Komplexitätstheorie Da der Verifikationsschritt beim Model-Checking größtenteils automatisch verläuft, ist die Frage der Berechnungskomplexität dieses Entscheidungsproblems hoch interessant. Die Komplexität von Model-Checking für diverse temporale Logiken wurde in [CES86], [Sch02], [EL87] untersucht. Das Model-Checking ist für CTL* PSPACE-vollständig und für CTL P-vollständig. Theoretische Hintergründe dafür werden in diesem Abschnitt einbezogen. Die Komplexitätsklasse P (PTIME), die Klasse der Probleme mit effizienten Algorith- men, wird oft als die Klasse der effizient lösbaren“ Probleme bezeichnet. Sie besteht ” aus allen Sprachen L, die einen Polynomialzeit-Entscheidungsalgorithmus haben. Ein Problem A heißt P-vollständig, falls A ∈ P und jedes andere Problem in P auf A re- duzierbar ist. P-vollständige Probleme werden manchmal als inhärent sequentiell (in- herently sequential) bezeichnet, da sie (wenn P ≠ NC) keine NC-Algorithmen haben. NC-Algorithmen laufen polylogarithmisch (in O(logc n), c konstant) an einem Paral- lelcomputer mit einer polynomiellen Anzahl von Prozessoren. Die Komplexitätsklasse NC beinhaltet die parallel effizient lösbaren Entscheidungsprobleme. Daher lassen sich P-vollständige Probleme nicht parallelisieren (wenn P ≠ NC). Es gibt einen NC-Algorithmus zum Parsen von kontextfreien Sprachen (CFL), d. h. CFL ⊆ NC. Deswegen ist die Klasse LOGCFL bei der Untersuchung der Komplexität des Model-Checkings für CTL von großem Interesse. Diese Klasse enthält alle mit logarith- mischem Speicheraufwand auf CFL reduzierbaren Probleme. Daher gilt LOGCFL⊆NC. Andererseits können Sprachen in LOGCFL von nichtdeterministischen Turing Maschi- nen in Polynomialzeit entschieden werden, die ein Arbeitsband logarithmischer Größe und zusätzlich einen Stack unendlicher Größe haben (siehe [BMT+ ]). Diese Eigenschaft von LOGCFL wird bei der Analyse der Komplexität vom Model-Checking-Problem für CTL erzielt. Im Rahmen dieser Arbeit werden aber nur die Algorithmen aus P ausgearbeitet. 12
3 Model-Checking für CTL Im vorherigen Kapitel wurde der allgemeine Model-Checking-Prozess aufgeführt. Ziel dieses Kapitels ist es, diesen Prozess auf CTL zu präzisieren. Nachdem das Model- Checking-Problem für CTL definiert wird, wird seine Komplexität in Betracht gezogen. Dabei werden die in [BMT+ ] (eine vorläufige, unveröffentlichte Version von [BMT+ 09]) präsentierten Hauptresultate sowie zwei Model-Checking-Algorithmen CTLpos -MC(EX, EG, EU, ER) und CTL-MC(ALL) vorgestellt, die in Polynomialzeit arbeiten. Die prak- tische Aufgabe der vorliegenden Arbeit besteht darin, diese Algorithmen zu implemen- tieren und ihre Effizienz zu vergleichen. 3.1 Formulierung des Problems In Abschnitt 2.3 wurde die Menge ALL von allen CTL-Operatoren erwähnt. Mit CTL(ALL) wird dann die Menge von CTL-Formeln bezeichnet. Bei Aufklärung der Kom- plexitätsfragen ist es hilfreich, nicht nur die gesamte Menge ALL, sondern auch kleinere Teilmengen davon zu betrachten. Definition 3.1.1 (CTL(T )) Sei T ⊆ ALL eine Menge von CTL-Operatoren. Mit CTL(T) wird die Menge von CTL-Formeln bezeichnet, in denen nur die booleschen Ope- ratoren {¬, ∧, ∨} und die CTL-Operatoren aus T erlaubt sind. Ferner können beliebige eingeschränkte Fragmente von CTL(T ) definiert werden. Für die vorliegende Arbeit wird das Fragment CTLpos (T ) benötigt, in dem CTL-Operatoren im Bereich einer Negation nicht auftreten dürfen: für a, b ∈ AP gilt • ¬EX a ∉ CTLpos (T ) • ¬(a ∧ ¬b) ∨ EX a ∈ CTLpos (T ) In Abschnitt 2.1 wurde das Model-Checking-Problem in der Frage formuliert, ob ein Modell eine Spezifikation erfüllt. Weiterhin muss das auf eine Kripke-Struktur (Modell) und eine CTL-Formel (Spezifikation) übertragen werden. Anschließend wird die Erfüll- barkeit einer CTL-Formel in Bezug auf eine Kripke-Struktur definiert. 13
3 Model-Checking für CTL Definition 3.1.2 (Model-Checking-Problem) Sei L ∈ {CTL, CTLpos }. Problem: L-MC(T) Eingabe: ⟨K, w, ϕ⟩, wobei für die einzelnen Komponenten gilt: K = (W, R, η) ist eine Kripke-Struktur, w ∈ W ist ein Zustand, ϕ ist eine L(T)-Formel. Frage: Erfüllt K im Zustand w die Formel ϕ, also K, w ⊧ ϕ? Definition 3.1.3 (Semantik) Seien K, w wie in der Definition 3.1.2 und x = (x1 , x2 , ...) ∈ W ω ein Pfad. Ferner seien ϕ, ψ Zustand- und χ, π Pfad-Formeln. Die Evaluie- rung einer Formel zu wahr wird folgendermaßen induktiv definiert. K, w ⊧ ⊺ immer, K, w ⊧ nie, K, w ⊧ p falls p ∈ AP und p ∈ η(w), K, w ⊧ ¬ϕ falls K, w /⊧ ϕ, K, w ⊧ (ϕ ∧ ψ) falls K, w ⊧ ϕ und K, w ⊧ ψ, K, w ⊧ (ϕ ∨ ψ) falls K, w ⊧ ϕ oder K, w ⊧ ψ, K, w ⊧ Aχ falls K, x ⊧ χ ∀x = (x1 , x2 , ...) mit x1 = w, K, w ⊧ χ falls K, x1 ⊧ χ, K, w ⊧ Xχ falls K, x2 ⊧ χ, K, w ⊧ [χUπ] falls ∃k ∈ IN, so dass K, xk ⊧ π und K, xi ⊧ χ∀1 ≤ i < k. Die Erfüllbarkeit der Formeln, in denen die übrigen CTL-Operatoren verwendet wer- den, kann mittels der in Tabelle 2.3 aufgelisteten Umwandlungsregeln überprüft werden. Außerdem sagt man, eine Zustand-Formel ϕ wird von einer Kripke-Struktur K erfüllt, wenn es einen Zustand w ∈ W gibt, so dass K, w ⊧ ϕ. Und analog, eine Pfad-Formel χ wird von einer Kripke-Struktur K erfüllt, wenn es einen Pfad x = (x1 , x2 , ...) gibt, so dass K, x ⊧ χ. Geschrieben: • K ⊧ ϕ ⇐⇒ ∃w ∈ W ∶ K, w ⊧ ϕ • K ⊧ χ ⇐⇒ ∃x = (x1 , x2 , ...) ∶ K, x ⊧ χ 3.2 Komplexität des Model-Checking-Problems für CTL Im Allgemeinen gilt Model-Checking für CTL als P-vollständig. Obwohl es in Polynomi- alzeit lösbar ist, lässt das Problem sich nicht parallelisieren (falls P ≠ NC). Daher werden Fragmente von CTL betrachtet, um leichtere Teilprobleme zu finden, die effizienter zu lösen sind. Die in [BMT+ ], [BMT+ 09] erhaltenen Resultate können folgendermaßen zusammenge- fasst werden. 14
3 Model-Checking für CTL 1. Nicht-parallelisierbare Fälle: P-Vollständigkeit liegt für alle CTL-Fragmente vor, in denen mindestens ein CTL-Operator benutzt wird. 2. Trivialfall: Für Fragmente ohne temporale Operatoren stimmt das Model-Che- cking-Problem mit der Auswertung einer aussagenlogischen Formel überein, und dieses Problem ist NC1 -vollständig, d. h. parallelisierbar. NC1 ist eine NC-Klasse der Sprachen, die in O(log1 n)-arbeitende Entscheidungsalgorithmen haben (siehe [BMT+ 09]). 3. Parallelisierbare und nicht-triviale Fälle: Model-Checking-Problem CTLpos -MC(T ) ist LOGCFL-vollständig, falls ∅ ⊊ T ⊆ {EX, EF} oder ∅ ⊊ T ⊆ {AX, AG} (vgl. [BMT+ 09]). Für diese Arbeit ist der erste Fall relevant. Auf diesen wird in Abschnitt 3.3 genauer eingegangen. 3.3 Model-Checking für CTL und CTLpos Dieser Abschnitt enthält wichtigste Ergebnisse zur Komplexität von Model-Checking für CTL und für das in Abschnitt 3.1 definierte negationsbeschränkte Fragment CTLpos . Die entsprechenden Entscheidungsalgorithmen werden hier vorgestellt und erörtert. 3.3.1 CTL-MC(ALL) Satz 3.3.1 CTL-MC(ALL) ∈ P In [CGP99] wurde ein Algorithmus vorgestellt, der das Problem CTL-MC(ALL) in Polynomialzeit entscheidet. Dieser wird im Weiteren beschrieben. Seien K = (W, R, η) eine Kripke-Struktur und ϕ eine CTL-Formel. Der Algorithmus bestimmt, in welchen Zuständen aus W die Formel ϕ erfüllt wird. Die Formel ϕ wird in die Teilformeln zerlegt. Unter einer Teilformel wird hier eine Formel verstanden, aus der mit Hilfe der Operatoren die betrachtete Formel konstruiert wird. Z. B. für ϕ = γ ∧ λ oder für ϕ = EXγ sind γ, λ die Teilformeln von ϕ. Jeder Zustand w wird mittels einer Menge label(w) markiert, zu der alle Teilformeln hinzugefügt werden, die in w erfüllt sind. Anfangs gilt: label(w) = η(w). Der Algorithmus läuft mehrere Stufen durch. Die Anzahl der Stufen entspricht dem Verschachtelungsgrad1 (Anzahl der vorkommenden Operatoren) der Formel ϕ. In der i-en Stufe sind Teilformeln des Verschachtelungsgrades i-1 bereits abgearbeitet. Nachdem eine Teilformel γ behandelt wurde, wird sie zu der Menge label(w) von denjenigen Zuständen w hinzugefügt, in denen γ wahr ist. Sobald der Algorithmus terminiert, gilt K, w0 ⊧ ϕ, falls ϕ ∈ label(w0 ). In Abschnitt 2.3 wurde beschrieben, dass jede CTL-Formel durch atomare Aussagen und die Operatoren ¬, ∨, EX, EU und EG konstruiert werden kann. Deswegen müssen in jeder Stufe sechs Fälle behandelt werden. Seien φ eine CTL-Formel und w ein Zustand, die auf der i-en Stufe betrachtet werden. 1 Verschachtelungsgrad ist 0, falls f ∈AP 15
3 Model-Checking für CTL 1. φ ∈ AP: φ wird akzeptiert, falls φ ∈ label(w). In diesem Fall wird keine Markierung vorgenommen, da label(w) mit η(w) initia- lisiert wird; 2. φ = ¬γ: markiert werden die Zustände, die mit γ nicht markiert sind. ∀v ∈ W, γ ∉ label(v): label(v) = label(v) ∪ φ. 3. φ = γ ∨ λ: betroffen sind diejenigen Zustände, die mit γ oder mit λ markiert sind. ∀v, u ∈ W, γ ∈ label(v), λ ∈ label(u): label(v) = label(v)∪φ, label(u) = label(u)∪φ. 4. φ = EXγ: markiert werden direkte Vorfahren der mit γ markierten Zustände. ∀v, u ∈ W, γ ∈ label(v), (u, v) ∈ R: label(u) = label(u) ∪ φ 5. φ = E(γUλ): markiert werden die Zustände, von denen aus ein Pfad existiert, der aus den mit γ markierten Zuständen besteht und mit dem mit λ markierten Zustand endet. Die Pfade werden rückwärts von den mit λ markierten Zuständen konstruiert. Dieser Fall wird in Algorithmus 1 behandelt. Algorithmus 1 Procedure CheckEU K, w0 ⊧ ϕ Eingabe: eine Kripke-Struktur K = (W, R, η), w0 ∈ W , ϕ = E(αUβ) 1: T ← {s ∣ β ∈ label(s)} 2: for all s ∈ T do 3: label(s) ← label(s) ∪ {E(αUβ)} 4: end for 5: while T is not empty do 6: choose s ∈ T 7: T ← T /{s} 8: for all t such that (t, s) ∈ R do 9: if ϕ ∉ label(t) and α ∈ label(t) then 10: label(t) ← label(t) ∪ {E(αUβ)} 11: T ← T ∪ {t} 12: end if 13: end for 14: end while 6. φ = EGγ: hier werden diejenigen Zustände markiert, von denen aus ein Pfad existiert, entlang dessen nur die mit γ markierten Zustände vorkommen. Um sol- che Pfade zu finden, wird aus der Kripke-Struktur eine reduzierte Kripke-Struktur K ′ = (W ′ , R′ , η ′ ) konstruiert, in die nur die mit γ markierten Zustände aus W und zugehörige Relationen aufgenommen werden. Formal: W ′ = {w ∈ W, γ ∈ label(w)}, R′ = R∣W ′ ×W ′ und η ′ = η∣W ′ . K ′ wird mit Hilfe des Algorithmus von Tarjan [AHU74] in nicht triviale Zusammenhangskomponenten zerlegt. Eine Zusammen- hangskomponente (strong connected component) C ist ein maximaler Teilgraph, in dem jeder Knoten in C von jedem anderen Knoten aus C über einen gerichteten 16
3 Model-Checking für CTL komplett in C verlaufenden Pfad erreichbar ist. C ist nicht trivial, falls sie entwe- der aus mehr als einem Knoten oder aus nur einem Knoten mit einer Selbstschleife besteht (C = {v ∈ W ′ }, (v, v) ∈ R′ ). Nachdem K ′ partitioniert wurde, wird nach den Zuständen gesucht, die zu nicht trivialen Zusammenhangskomponenten gehö- ren. Dabei wird rückwärts über R′ abgearbeitet, und die erforderlichen Zustände werden markiert. Diesen Fall stellt Algorithmus 2 dar. Algorithmus 2 Procedure CheckEG K, w0 ⊧ ϕ Eingabe: eine Kripke-Struktur K = (W, R, η), w0 ∈ W , ϕ = EGα 1: S ′ ← {s ∣ α ∈ label(s)} 2: SCC ← {C ∣ C is a nontrivial SCC of S ′ } 3: T ← ⋃C∈SCC {s ∣ s ∈ C} 4: for all s ∈ T do 5: label(s) ← label(s) ∪ {EGα} 6: end for 7: while T is not empty do 8: choose s ∈ T 9: T ← T /{s} 10: for all t such that t ∈ S ′ and (t, s) ∈ R do 11: if ϕ ∉ label(t) then 12: label(t) ← label(t) ∪ {EGα} 13: T ← T ∪ {t} 14: end if 15: end for 16: end while Das Abarbeiten jeder der Teilformeln von ϕ benötigt O(∣W ∣ + ∣R∣)-Zeit2 . Die Kom- plexität des gesamten Algorithmus beträgt somit O(∣ϕ∣ ⋅ (∣W ∣ + ∣R∣)) (Polynomialzeit), wobei ∣ϕ∣ die Anzahl der verschiedenen Teilformeln von ϕ ist. 3.3.2 CTLpos -MC(EX, EG, EU, ER) Es ist bemerkenswert, dass sich jede obere Grenze für CTL-MC(T ) auch auf CTLpos -MC(T ) (für alle T ) übertragen lässt. Dennoch lässt sich die Komplexität von CTLpos-MC(T ) verbessern, wenn in T nur bestimmte Operatoren verwendet werden (vgl. [BMT+ 09]). Dies ist eine zentrale Idee bei der Untersuchung des CTLpos-Fragmentes. Au- ßerdem steht im Hintergrund die Eigenschaft von LOGCFL-Sprachen, dass sie sich mit einer nichtdeterministischen Turing Maschine in Polynomialzeit entscheiden lassen, die ein Arbeitsband logarithmischer Größe und einen unendlichen Stack besitzt. In diesem 2 Im ersten Fall wird O(∣W ∣ + ∣AP ∣)-Zeit beansprucht, aber es wird angenommen, dass das zu analysie- rende System in Bezug auf das Zusammenspiel zwischen den Komponenten(|R|) im Vergleich zu der Anzahl der Eigenschaften des Systems (|AP |) genügend komplex ist. Deswegen wird die Komplexität auf O(∣W ∣ + ∣R∣) verallgemeinert. 17
3 Model-Checking für CTL Abschnitt wird aber ein in Exponentialzeit arbeitender Algorithmus CTLpos-MC(T ) vor- gestellt, der dem in Abschnitt 3.3.1 aufgeführten Algorithmus CTL-MC(T ) in Bezug auf ihre Effizienz weiter unten gegenübergestellt wird. Satz 3.3.2 Sei T eine Menge von CTL-Operatoren, so dass alle Operatoren in T exis- tenziell oder alle Operatoren in T universal sind. Dann ist CTLpos -MC(T) ∈ P. Als Erstes wird der Fall betrachtet, dass in T nur existenzielle Operatoren erhältlich sind. O. B. d. A. sei T ∈ {EX, EG, EU, ER}. Es wird behauptet, dass Algorithmus 3 entscheidet, ob die Kripke-Struktur K = (W, R, η) die CTLpos (T )-Formel ϕ im Zustand w0 ∈ W erfüllt. S sei ein Stack zum Speichern von Paaren (ϕ, w) ∈ CTLpos (T ) × W . Jede Formel wird ähnlich wie im CTL-MC(ALL)-Algorithmus abgearbeitet. Sie wird je nach dem verwendeten Operator in die Teilformeln zerlegt und entsprechend behan- delt. Ein deutlicher Unterschied liegt in dem Fall vor, wenn eine Pfad-Formel überprüft werden muss, z. B. ϕ = EGα oder ϕ = E(αUβ). Hier muss ein Pfad aus allen möglichen aus dem betrachteten Zustand ausgehenden Pfaden nichtdeterministisch gefunden wer- den. α wird dann in jedem Zustand entlang dieses Pfades geprüft. Im CTL-MC(ALL)- Algorithmus werden für solche Formeln erst die Zustände gefunden, in denen α erfüllt wird. Danach werden aus diesen Zuständen starke Zusammenhangskomponenten und aus diesen Ergebnispfade konstruiert. Die Konstruktion des Algorithmus macht die oben erwähnte Eigenschaft der LOGCFL- Sprachen erkennbar. Der Algorithmus lässt sich mit einer Turing Maschine mit einem Stack und einem Arbeitsband logarithmischer Größe entscheiden. Wenn der Algorithmus in Polynomialzeit arbeiten würde, dann könnte man das Problem CTLpos -MC(EX, EG, EU, ER) zu LOGCFL-Sprachen einordnen. Das ist aber für den Fall ϕ = EGα oder ϕ = E(αUβ) unmöglich. Das Problem liegt für die Formeln vor, die nach dem folgenden Schema geschachtelt sind. Sei ϕ = EGα0 , wobei α0 eine Formel ist, die als Teilformel EGα1 enthält usw. Z. B. ϕ = EG(x0 ∨EG(x1 ∧EG(x2 ...))). Für jede Teilformel αi,i=0,... wird ein neuer Pfad geraten und jeweils |W|-mal auf den Stack gelegt. Analog gilt dies auch für die EU-Formeln. Dies führt zum exponentiellen Bedarf in der Stackgröße. Der Algorithmus benötigt exponentielle und nicht mehr polynomielle Zeit, wie es bei LOGCFL gefordert wird. ER-Formeln stellen eine Kombination von EG- und EU-Formeln dar. EX-Formeln können polynomiell mit der Turing Maschine abgearbei- tet werden. Die übrigen Formeln repräsentieren Trivialfälle. Für die EG-, EU-Formeln besitzt der Algorithmus folgende Komplexität. Um alle Pfade abzuarbeiten, braucht man O(2n ) Zeit. Bei geschickter Implementierung mit dem direkten Zugriff auf Teilfor- meln im Stack ergibt sich O(2log(n) ) = O(nO(1) ) Bedarf. Folglich ist der Algorithmus für CTLpos -MC(EX, EG, EU, ER) theoretisch polynomiell. Die Tatsache, dass der Algorithmus immer terminiert, folgt daraus, dass jede Teil- formel von ϕ nicht mehr als |W |-mal im Stack S gespeichert wird. Außerdem zeigt die Induktivität der Struktur von Formeln, dass der Algorithmus genau dann false zurück- gibt, wenn für alle aus dem Stack S geladenen Paare (φ, w) K, w ⊭ φ gilt. Folglich terminiert der Algorithmus mit true, genau dann wenn K, w ⊧ ϕ. 18
3 Model-Checking für CTL Algorithmus 3 Entscheide, ob K, w ⊧ ϕ Eingabe: eine Kripke-Struktur K = (W, R, η), w0 ∈ W , ϕ ∈ CTLpos (T) Ausgabe: true (falls K, w ⊧ ϕ) oder false (sonst) 1: push(S, (ϕ, w0 )) 2: while S is not empty do 3: (ϕ, w) ← pop(S) 4: if ϕ is a propositional formula then 5: if ϕ evaluates to false in w under η then 6: return false 7: end if 8: else if ϕ = α ∧ β then 9: push(S, (β, w)) 10: push(S, (α, w)) 11: else if ϕ = α ∨ β then 12: nondet. push(S, (α, w)) or push(S, (β, w)) 13: else if ϕ = EXα then 14: nondet. choose w′ ∈ {w′ ∣ (w, w′ ) ∈ R} 15: push(S, (α, w′ )) 16: else if ϕ = EGα then 17: guess a path (wi )1≤i≤∣W ∣ such that w1 = w 18: for all 1 ≤ i ≤ ∣W ∣ do 19: push(S, (α, wi )) 20: end for 21: else if ϕ = E(αUβ) then 22: guess k ≤ ∣W ∣ and a path (wi )1≤i≤k such that w1 = w 23: for all 1 ≤ i < k do 24: push(S, (α, wi )) 25: end for 26: push(S, (β, wk )) 27: else if ϕ = E (αRβ) then 28: guess γ ∈ {EGβ, E(βU(α ∧ β))} 29: push(S, (γ, w)) 30: end if 31: end while 32: return true 19
3 Model-Checking für CTL Bei der Implementierung dieses Algorithmus kollidiert man mit den Problemen, die sich durch den in den Zeilen 12, 14, 17, 22, 28 vorkommenden Nichtdeterminismus be- kunden. Außerdem, um bessere Effizienz zu erreichen, müssen die Pfade in den Zeilen 15, 19, 24 auf dem Stack knotenweise und nicht als Ganzes gespeichert und bearbeitet werden. Diese sowie weitere Besonderheiten bezüglich der Implementierung werden in Kapitel 4 besprochen. Der Fall, wenn alle Operatoren in T universal sind, folgt aus Abgeschlossenheit von P unter dem Komplement und kann analog gelöst werden (Eϕ ≡ ¬A¬ϕ). 20
4 Design und Implementierung Im vorigen Kapitel wurden die Model-Checking-Algorithmen für CTL-MC(ALL) und CTLpos -MC(EX, EG, EU, ER) präsentiert. Diese werden im Rahmen dieser Diplomar- beit in Java implementiert. In diesem Kapitel werden Implementierungsaspekte erläutert. Dabei wird ein existierendes Programm um weitere Funktionalitäten erweitert. Dieses Programm wird in Abschnitt 4.1 vorgestellt. Die ausführliche Beschreibung findet man in [Sol09]. Die geänderte Klassenstruktur und die neuen Möglichkeiten des Programms werden auch in diesem Kapitel veranschaulicht. 4.1 Basisprogramm Als Basis wurde ein Programm verwendet, das im Rahmen einer anderen Diplomarbeit am Institut für theoretische Informatik der Leibniz Universität Hannover entstanden ist. Dieses Programm wurde mit dem Ziel entwickelt, einige Model-Checking-Algorithmen für LTL zu realisieren. Die Benutzeroberfläche des Hauptfensters ist in Abbildungen 4.1 zu sehen. Das Hauptfenster besteht aus drei Bereichen, die sich auf Kripke-Struktur, Formel und Algorithmen beziehen. In jedem Bereich gibt es Buttons zum Aufrufen diverser Aufgaben und ein Textfeld, in dem eine Kripke-Struktur, eine Formel oder Ergebnisse der Algorithmen veranschaulicht werden. Folgende Funktionalitäten sind bereits vorhanden: • Erstellung einer neuen Kripke-Struktur bzw. einer neuen Formel; • Speicherung einer Kripke-Struktur bzw. einer Formel in einer Datei; • Laden einer Kripke-Struktur bzw. einer Formel aus einer Datei; • Zeichnen einer Kripke-Struktur; • Starten der Model-Checking-Algorithmen für LTL angewendet auf die erstellte/ge- ladene Kripke-Struktur und die erstellte/geladene Formel. Die implementierte Datenstruktur, die eine Kripke-Struktur repräsentiert, und alle zuge- hörigen Funktionalitäten werden übernommen. Die Visualisierung der Kripke-Struktur wird überarbeitet und um einige Funktionen ergänzt. Da das Basisprogramm speziell für das Model-Checking für LTL entwickelt wurde, müssen die Operationen zur Bearbei- tung der Formeln angepasst und erweitert werden, um CTL-Formeln zu erfassen, um die in dieser Arbeit auszuarbeitenden Model-Checking-Algorithmen verwenden zu können. Weiter unten werden diese und andere Erweiterungen des Basisprogramms erörtert. 21
4 Design und Implementierung Abbildung 4.1: Das Hauptfenster des Basisprogramms (Bild aus [Sol09]) 4.2 Neue Klassenstruktur und die Implementierungsaspekte In diesem Abschnitt wird die erweiterte Klassenstruktur des Programms erläutert. Abbil- dung 4.2 stellt die Programmlogik dar, und Abbildung 4.3 zeigt die Klassenstruktur der Benutzerschnittstelle. Die für diese Arbeit relevanten Klassen des Basisprogramms wer- den ohne Attribute bzw. Operationen abgebildet. Die komplett übernommenen Klassen sind in schwarz und die erweiterten Klassen sind in grün dargestellt. Die neuen Klassen sind in blau hervorgehoben. Die get- und set-Methoden werden übersichtshalber nicht dargestellt. 22
4 Design und Implementierung Proposition 0..1 0..2 1..* FormulaCTLpos 0..2 #not: boolean #and: boolean FormulaCTL #or: boolean -EF: boolean #EX: boolean -AF: boolean #EG: boolean -AX: boolean #EU: boolean -AG: boolean #ER: boolean -AU: boolean +isProposition(): boolean -AR: boolean +stringToFormula(String): FormulaCTLpos +isProposition(): boolean +stringInPrefixToFormula(String): FormulaCTLpos +stringToFormula(String): FormulaCTL +formulaToString(): String +stringInPrefixToFormula(String): FormulaCTL +formulaToStringInPrefix(): String +formulaToString(): String #getIndexOfMainOperator(String): int +formulaToStringInPrefix(): String -modifyAccordingDeMorgan() +convert() -getToken(String): String -getToken(String) ModelCheckingCTLpos ModelCheckingCTL -formulaCTLpos: FormulaCTLpos -formulaCTL: FormulaCTL -kripke: Kripke -kripke: Kripke -state: State -labeledStates: HashMap -paths: ArrayList +modelCheckingCTL(FormulaCTL): HashMap +modelCheckingCTLposArrayList(Kripke,FormulaCTLpos, -checkPropositions(Proposition): HashMap +modelCheckingCTLposTree(Kripke,FormulaCTLpos, -checkNot(HashMap): HashMap -checkOr(HashMap,HashMap): HashMap -checkEX(HashMap): HashMap -checkEU(HashMap,HashMap): HashMap -checkEG(HashMap): HashMap -getSCC(HashMap): ArrayList State Kripke -key: int -... -name: String -allTransVector: ArrayList 1..* 1 -initial: boolean ...() -propositions: String[] +edit() -transitions: ArrayList +createRandomKripke(int,int,int) -computaionTree : TreeNode -getRandomPropositions(int): String[] -paths: ArrayList 1 -index: int -lowLink: int ...() +evaluatePropositionalFormula(FormulaCTLPos): booelan 2 +getPredecessorStates(Kripke): HashMap Transition +getSuccStates(Kripke): int[] +formPaths(int,Kripke) +createComputationTree(Kripke): TreeNode 0..1 TreeNode -value: T -parent: TreeNode -leftChild: TreeNode -rightSibling: TreeNode -depth: int +addChild(T): TreeNode +addRightSibling(T): TreeNode +getChildren(): ArrayList Abbildung 4.2: Klassendiagramm für Programmlogik 23
4 Design und Implementierung FormulaCTL ModelCheckingCTL State ModelCheckerCTL -formulaCTL: FormulaCTL -formulaCTLpos: FormulaCTLpos -kripke: Kripke FormulaCTLpos -result: boolean -selectedStates: ArrayList +labelTrueStatesInGraph() ModelCheckingCTLpos -getStatesList(): ArrayList -setClickedStatesInGraph(ArrayList) GraphVisualization Kripke +draw(Kripke) +saveImage(Kripke) SettingsFrame ModelChecker -formulaFile: File -kripkeFile: File +loadProperties() +saveProperties() Formula ModelCheck Abbildung 4.3: Klassendiagramm der Benutzerschnittstelle Kripke-Struktur Die Klasse Kripke stellt eine Kripke-Struktur als eine Liste von Zuständen dar, die mittels der Klasse State realisiert werden. Jeder Zustand hat eine eindeutige Identi- fikationsnummer, einen Namen und eine Liste der atomaren Aussagen, die in diesem Zustand gelten. Das Attribut initial gibt an, ob ein Zustand der Startzustand in der Kripke-Struktur ist. Übergänge zwischen den Zuständen in der Kripke-Struktur werden mittels der Klasse Transition gespeichert. Neben den übernommenen Funktionalitäten, die Kripke-Struktur zu erstellen/speichern/laden, kann sie jetzt auch geändert werden (edit()). Außerdem wird ermöglicht, eine zufällige Kripke-Struktur generieren zu lassen (createRandomKripke(int, int, int)). Als Argumente werden die Anzahl von Zuständen S, die Anzahl von Übergängen T , die aus jedem Zustand ausgehen, sowie die maximale Anzahl von atomaren Aussagen P , die jedem Zustand zugeordnet werden. Die Generie- rung geschieht folgendermaßen. 1. Es wird eine Menge der Größe S von Zuständen erzeugt. Als Namen werden die natürliche Zahlen vergeben. 2. Jedem Zustand werden Übergänge hinzugefügt. Die Anzahl der Übergänge T ist für jeden Zustand fest. Die Endzustände von Übergängen werden mittels einer Zufallsfunktion ermittelt. 24
4 Design und Implementierung 3. Jeder Zustand wird mit einer Menge von atomaren Aussagen beschriftet. Diese werden auch zufällig mittels getRandomPropositions(int) generiert. Als atomare Aussagen werden hier die Buchstaben des lateinischen Alphabets verwendet. Das heißt, dass jeder Zustand maximal 26 atomare Aussagen haben kann. Für jeden Buchstaben wird eine Zufallszahl generiert. Wenn diese Zahl größer als 0,5 ist, wird dieser Buchstabe dem aktuellen Zustand zugeordnet. Der letzte mögliche Buchstabe entspricht dem übergebenen Parameter P . Mit anderen Worten: jeder Zustand wird mit keinen oder mit maximal S ersten Buchstaben des lateinischen Alphabets beschriftet. Die Klasse State wurde um die Attribute index und lowLink erweitert, die den Aufbau von den für Algorithmus 2 notwendigen Zusammenhangskomponenten ermöglichen. Eine weitere relevante Methode getPredecessorStates(Kripke), die zu einem Zustand sämtliche direkten Vorfahren findet, wird auch in dieser Klasse implementiert. Mittels der Methode evaluatePropositionalFormula(FormulaCTLpos) wird überprüft, ob eine CTLpos-Formel, in der keine CTL-Operatoren, sondern nur die booleschen Operatoren {¬, ∧, ∨} vorhanden sind, in dem aktuellen Zustand erfüllt wird. Algorithmus 3 benötigt bei der Analyse von EG-, EU-Formeln aus einem Zustand ausgehende Pfade. Diese können mittels der vom Basisprogramm übernommenen Metho- den getSuccStates(Kripke) und formPaths(int, Kripke) ermittelt werden. formPaths(...) konstruiert solche Pfade. Jeder Pfad ist eine Liste von Zuständen. Alle aus einem Zustand ausgehenden Pfade werden als eine Liste von solchen Listen gespeichert. In Abschnitt 3.3.2 wurde erwähnt, dass man eine bessere Effizienz erreichen kann, wenn Zustände auf den Pfaden knotenweise gespeichert werden. Um dies zu ermöglichen, wurde die Klasse TreeNode entwickelt, die einen Baum als Datenstruktur realisiert und alle nötigen Methoden bereitstellt. Jeder Zustand ist ein Knoten im Baum. Die von ihm erreichbaren Zustände sind seine Kinderknoten usw. Die Methode createComputationTree(Kripke) erzeugt einen Berechnungsbaum, in dem alle ausgehenden Pfade durch Tiefendurchlauf rekonstruiert werden können. In der Instanzvariable computaionTree wird der Wurzel- knoten des Berechnungsbaumes gepeichert. Algorithmus 3 wird zweimal implementiert, um die beiden Möglichkeiten zu vergleichen, Pfade als Liste von Listen und als einen Baum abzuarbeiten. CTL-Formel CTL-Formeln werden im Hinblick auf Definition 2.3.1 mit Hilfe der Klassen Proposition, FormulaCTLpos und FormulaCTL implementiert. Jede CTL-Formel ist eine Instanz der Klasse FormulaCTLpos bzw. FormulaCTL und besteht aus CTL-Teilformeln, die in einer Liste gespeichert werden. Der verwendete Operator wird registriert, indem das entsprechende Attribut der Klasse FormulaCTLpos bzw. FormulaCTL auf wahr“ ” gesetzt wird. Dabei gelten die üblichen Prioritätsregeln, und alle binären Operatoren sind linksassoziativ. Jede Formel mit einem binären Operator (z. B. OR, AND, EU, AR) wird somit als eine Liste mit zwei Elementen und jede Formel mit einem unären Operator (z. B. NOT, EX, AG) mit einem Element dargestellt. 25
4 Design und Implementierung Die einfachste Form einer CTL-Formel ist eine atomare Aussage. Solche Formel wird als eine Liste mit einem Element, einer Instanz der Klasse Proposition, erzeugt. Alle Attribute werden in diesem Fall mit falsch“ initialisiert. Formeln dieser Art können mit ” Hilfe der Methode isProposition() identifiziert werden. Jede FormulaCTLpos- oder FormulaCTL-Formel besteht folglich entweder aus einem Objekt der Klasse Proposition oder aus einer Liste mit einem oder zwei Objekten der Klasse FormulaCTLpos bzw. FormulaCTL. Durch die Klasse FormulaCTLpos können CTLpos -Formeln erzeugt werden, in de- nen CTL-Operatoren nicht negiert werden dürfen. Außerdem ist die Menge der CTL- Operatoren auf die Menge {EX, EG, EU, ER} eingeschränkt, da nur diese für den Algo- rithmus 3 benötigt werden. Die Klasse FormulaCTL enthält sowohl die von FormulaCTLpos geerbten Attribute als auch weitere Attribute, die es zusammen ermöglichen, beliebige CTL-Formeln zu bilden. Die Formeln können über eine Benut- zerschnittstelle in textueller Form in der Infix- oder Präfix-Notation eingegeben wer- den. Das Erstellen der Formeln aus dem Eingabetext geschieht mittels der Methoden StringToFormula(String) und StringInPrefixToFormula(String). Dies erfolgt, indem die Eingabe analysiert wird und ein Operator der Formel mittels der getIndexOfMainOperator (String) und getToken(String) gefunden wird. Folglich werden die Teilformeln der Formel ermittelt, die weiterhin analog in die Tiefe“ geparst wer- ” den. Die Konvertierung in die andere Richtung passiert mittels FormulaToString() bzw. FormulaToStringInPrefix (). Die Methode modifyAccordingDeMorgan() bringt eine CTLpos -Formel nach den De Morganschen Gesetzen in so eine Form, dass die Negationen nur direkt von den ato- maren Aussagen stehen. Diese Umwandlung vereinfacht die Auswertung der Formel in Algorithmus 3: K, w0 ⊧ ¬p, wenn p ∈ AP und p ∉ η(w0 ). Dies ermöglicht die Methode evaluatePropositionalFormula(FormulaCTLpos) in der Klasse State. Die Methode convert() in der Klasse FormulaCTL wandelt eine CTL-Formel in ei- ne äquivalente um, die aus atomaren Aussagen und den Operatoren ¬, ∨, EX, EU und EG besteht. Diese Methode ist für CTL-MC(ALL) von großer Bedeutung, da diese Ope- ratoren eine minimale Menge der Operatoren bilden, um alle möglichen CTL-Formeln konstruieren zu können. Die Konvertierung erfolgt mittels der in der Tabelle 2.3 aufge- führten Regeln. Algorithmen Die Klassen ModelCheckingCTLpos und ModelCheckingCTL bilden den Kern des Programms. Sie enthalten nämlich die Model-Checking-Algorithmen CTLpos -MC(EX, EG, EU, ER) bzw. CTL-MC(ALL). Um den CTLpos -Algorithmus ausführen zu können, müssen eine Kripke-Struktur, ein Zustand in der Kripke-Struktur und eine zu prüfende CTLpos -Formel bekannt sein. Die- se Argumente werden in den entsprechenden Instanzvariablen gespeichert. Die Methoden modelCheckingCTLposArrayList(Kripke, FormulaCTLpos, State) und modelChecking- CTLposTree(Kripke, FormulaCTLpos, State) stellen die zwei oben vorgestellten Imple- mentierungsmöglichkeiten des Algorithmus 3 dar. Die Ergebnisse des Model-Checkings 26
4 Design und Implementierung werden in den Variablen result und paths gespeichert. result wird auf wahr“ gesetzt, ” falls die Kripke-Struktur kripke die Formel formulaCTLpos im Zustand state erfüllt. In Abhängigkeit davon, ob es um eine Zustands- oder Pfad-Formel handelt, werden in paths Zustände bzw. Pfade verfasst, in denen die Erfüllbarkeit vorliegt. In Abschnitt 3.3.2 wurden die Implementierungsschwierigkeiten des Algorithmus 3 erwähnt. Hier liegt das Problem vor, dass man nichtdeterministisch mehrere Teilfor- meln oder Zustände abarbeiten ( nondet. choose“) oder aus mehreren einen Pfad oder ” einen Zustand aussuchen ( guess“) muss, in denen eine bestimmte Eigenschaft – d. h. ” eine Formel – erfüllt wird. Dieser Nichtdeterminismus wird durch die Überprüfung je- der Teilformel, jedes Zustandes und jedes Pfades der Reihe nach ersetzt, die in Frage kommen. Da es sich um die existentiellen Formeln handelt, kann man die Abarbeitung abbrechen, sobald eine Forderung (ein Zustand für die EX- oder ein Pfad für die EG- bzw. EU-Formeln) erfüllt wurde. Im schlimmsten Fall müssen aber alle Kandidaten überprüft werden. Betrachten wir den Fall ϕ = EGα. Wenn man alle aus einem Zustand w0 ausgehen- den Pfade betrachtet, hat man die exponentielle Anzahl von Möglichkeiten: ∣T ∣∣T ∣ , wobei ∣T ∣ die Anzahl aus einem Zustand ausgehender Übergänge ist. Die Laufzeit der Abarbei- tung der Pfade ist entsprechend groß. Wenn die Pfade als ArrayList gespeichert sind, wird jeder Pfad vom ersten bis zum letzten Zustand auf die Erfüllbar- keit der Formel α geprüft. Die Situation ändert sich, wenn die Pfade in einem Baum gefasst sind. Abbildung 4.4 zeigt diese zwei Abarbeitunsmöglichkeiten. Oben ist eine Kripke-Struktur dargestellt. Die Zustände sind mit den atomaren Aussagen versehen. Sei ϕ = EGa. Unten links ist die Liste mit den Pfaden, rechts davon ist der entspre- chende Berechnungsbaum. Die Pfade sowie der Berechnugsbaum sind unendlich, werden aber auf die Anzahl von Zuständen in der Kripke beschränkt, da die Pfade sonst einen Zyklus enthalten. Der gestrichelte Pfeil zeigt die Reihenfolge, in der die Zustände über- prüft werden, ob die Formel α = a in diesen gilt. Bei der zweiten Implementierung wird nach einem falschen“ Zustand, in dem die Teilformel α nicht gilt, zu seinem rechten ” Geschwister übergegangen. Das wird solange durchgeführt, bis es noch solche vorhanden sind und noch kein Pfad gefunden wurde. Dies wird mittels des iterativen Tiefendurch- laufs (siehe [AUH82]) realisiert, bei dem zu jedem Knoten seine rechten Geschwister in einem Stack gespeichert werden. Im Gegensatz zu der ersten Implementierung wird so- mit die Überprüfung in allen vorherigen Zuständen gespart. Eine weitere Möglichkeit an der Laufzeit zu gewinnen, ist die Speicherung von Ergebnissen des Model-Checkings in den geprüften Zuständen. Das bedeutet, dass nachdem die Zustände a“, a,b“ und b“ ” ” ” geprüft wurden, wird für die Formel α = a gespeichert, dass sie in den Zuständen a“ ” und a,b“ erfüllt wird. Wenn der zweite Pfad im Baum analysiert wird, muss der Model- ” Checking-Algorithmus im nächsten potenziellen Zustand nicht mehr ausgeführt werden. Die schon ermittelten Ergebnisse müssen nur gelesen werden. Dieser Ansatz beansprucht einen zusätzlichen Speicher, vermindert aber die Laufzeit. Weiterhin setzt der Algorithmus einen Stack ein. Um den Nichtdeterminismus zu lö- sen, müssen alle möglichen Zustände bzw. Pfade sowie entsprechende Formeln im Stack gespeichert werden. Zusätzlich muss der Typ der Formeln bei der Speicherung ihrer Teil- formeln mit angegeben werden, was jedoch für die Formeln ohne temporale Operatoren 27
Sie können auch lesen