14. Modální a temporální logiky a jejich použití
Problém této otázky ve vztahu ke studiu na FI je, že je rozházena přes více předmětů a v každém se probírá trochu jinak. Navíc jde rozlišit:
Tyto předměty (a k nim příslušející materiály) jsou zároveň poměrně dobrým zdrojem ke studiu. Pro účely této otázky se následující text pokouší obsáhnout oba dva přístupy.
Tento text lze více méně použít jako studijní materiál s tím, že pokud potřebujete hlubší pochopení nějakého tématu, je dobré podívat se do materiálů výše uvedených předmětů. LTL a CTL jsou poměrně důležité (v praxi) a proto je taky dobré vědět, jak se od sebe liší.
Pokud máme algoritmus, můžeme jeho funkci (nebo význam) popsat pomocí vstupní a výstupní podmínky, které jsou formálně zapsaná jako logická formule. Na jejich základě můžeme zkusit dokázat, že program má danou funkci, tedy že na vstupech splňující vstupní podmínku vždy skončí a jeho výstup bude splňovat podmínku výstupní. Když chceme něco takového udělat pro systém, který obsahuje paralelismus, nebo jeho konání nekončí, klasická (prvořádová) logika nám přestává stačit. Přitom takové systémy mají velký praktický význam – patří mezi ně například operační systémy a komunikační protokoly.
Modální a temporální logiky slouží k formální specifikaci (potenciálně) nekonečného chování systémů. Jde jimi vyjádřit celá řada zajímavých vlastnosti, jako například:
V praxi jsou zajímavé především temporální logiky, protože mají větší vyjadřovací sílu (respektive, modální logiky jsou „zahrnuty“ v CTL), lépe se v nich vyjadřují zajímavé vlastnosti a existuje automatická procedura pro ověření, zda daný model systému splňuje formuli temporální logiky, neboli model checking.
Logické formule se typicky nevztahují k skutečným systémům, ale k jejich modelům. Existují dva základní (a do jisté míry záměnné) formální modely systémů (také můžeme říct jejich stavových systémů). Oba dva jsou složeny ze stavů a přechodů mezi nimi. Rozdíl je pouze v tom, jestli jsou značky na přechodech nebo na stavech.
Labelled Transition System (LTS), neboli Označený přechodový systém
Typicky píšeme místo .
Kripkeho struktura (KS)
Atomické propozice jsou typicky nějaké Boolovské výrazy, tj. můžeme říct, že platí v , když .
Různé zdroje uvádějí tyto definice různě. Například u KS se může vynechat množina atomických propozic. Typické je ještě přidat k definici počáteční stav nebo jejich množinu. Důležité je:
Oba dva modely se mezi sebou dají převádět, ne vždy se ale zachovají množiny stavů. Typicky se setkáváme s převodem KS do LTS1):
Převod KS do LTS
Tedy označíme přechody vedoucí do každého stavu atomickými propozicemi, kterými je daný stav označen. Počáteční stavy se zachovávají.
V praxi, především co se týče model checkingu, se používají spíše Kripkeho struktury. Z teoretického hlediska jsou zase zajímavé LTS, protože na LTS je definován modální μ-kalkulus (viz níže)2). Z toho důvodu v tomto textu definuju různé logiky různým způsobem – modální na LTS a temporální na KS. Když použijeme výše uvedený převod, snadno získáme sémantiku temporálních logik na LTS.
Důležitá poznámka: Ani jedna struktura nemusí být konečná! Pokud není, je typicky zadaná implicitně, tedy místo přechodové relace máme funkci, která pro každý stav vrací jeho následníky, tj (pro KS – pro LTS ještě potřebujeme označení přechodů). Taky pak potřebujeme množinu počátečních stavů, nebo prostě nějaký stav, odkud začít.
Mějme nějaký program. Stavy jsou zřejmě dané ohodnocením proměnných a mezi nimi se přechází pomocí příkazů programu (tohle odpovídá small step operační sémantice – viz 12-tei). LTS můžeme vytvořit tak, že každý přechod označíme příkazem, který jej provedl. KS můžeme vytvořit tak, že si vytvoříme nějaké Boolovské výrazy nad proměnnými (jako ) a pokud v daném stavu platí, přidáme jej do jeho označení. Pokud chceme KS převést na LTS, přesunou se tyto výrazy na přechody, ale ztratíme informaci o tom, jaké příkazy provádějí přechody mezi jednotlivými stavy.
Kdybychom chtěli vytvořit implicitní reprezentaci, musíme si ještě do stavu přidat to, na jakém místě programu se nacházíme (abychom věděli, jaké příkazy se můžou provést) a nový stav se vypočítá podle možných příkazů.
Podobně se dá vytvořit stavový systém pro model v CCS (viz 15-tei), kde jednotlivé stavy jsou procesy a přechody mezi nimi jsou označené akcí, kterou provedou.
Obecně platí, že pokud máme nějaký programovací jazyk, model programu je dán jeho small-step operační sémantikou. Pro modální logiky má význam i big-step operační sémantika, ale o tom až níže.
Platnost formulí modálních a temporálních logik se typicky vztahuje ke stavu a popisuje chování, které v daném stavu začíná. Různé logiky to dělají různým způsobem. Zatímco modální logiky se zabývají všemi následníky daného stavu a popisují zda všechny nebo některé splňují danou podmínku, temporální logiky se typicky dívají dále do budoucna a sledují možná chování systému začínající v tomto stavu. Na to, co přesně se tímto chováním myslí, jsou dva základní náhledy:
Obě tyto logiky jsou užitečné – ačkoliv některé vlastnosti se dají zapsat pomocí formulí LTL i CTL, pro každou z těchto logik existují vlastnosti, které nejdou zapsat pomocí té druhé. Existuje ještě logika CTL*, která zahrnuje obě tyto logiky.
Modální logiky se vyjadřují o následnících stavu. Zde si uvedeme Hennessyho-Milnerovu logiku (HML). Její syntax je definována následující abstraktní syntaktickou rovnicí:
Syntax Hennessyho-Milnerovy logiky
Dále zavedeme trochu syntaktického cukru. Můžeme používat všechny spojky známé z výrokové logiky (negace a konjunkce tvoří úplný systém) a označíme , což znamená, že existuje následník pod a platí v něm .
Sémantika HML je dána na LTS, takže množina atomický propozic je libovolná a nemusí nutně souviset s množinou atomických propozic v KS3). Kromě LTS tedy budeme ještě potřebovat funkci, která udává význam atomických propozic – valuaci.
Modální model
Samozřejmě, pokud pracujeme s KS, bude nás určitě zajímat valuace, která odpovídá atomickým propozicím platným v jednotlivých stavech. Splněnost formule je dána pro každý stav:
Sémantika HML
Poznámka: Pokud stav nemá následníka pod , triviálně pro libovolnou formuli .
Splněnost jde rozšířit na model ( nebo když je splněna pro všechny stavy) a pro systém (když je splněna pro všechny valuace).
Co lze s pomocí takové logiky vyjádřit?
Vlastnosti začínají být zajímavé, když se přesuneme do splněnosti pro daný systém, tedy když atomické propozice můžou označovat libovolnou množinu stavů (i prázdnou):
Zajímavé je spojení s big-step operační sémantikou programů (viz 12-tei), kde když provedení programu ve stavu skončí ve stavu . Pokud označuje vstupní a výstupní podmínku, určuje formule korektnost programu .
LTL je nejznámějším reprezentatem temporálních logik, které se vyjadřují o bězích v Kripkeho struktuře (nebo LTS).
Běh v KS
Běh je typicky nekonečný. Může se stát, že běh v některém stavu končí (pokud nemá žádného následníka). Technicky to jde řešit dvěma způsoby (v podstatě ekvivalentními):
Pro naše účely si zavedeme, že označuje tý stav běhu a označuje jeho tý suffix, i.e. .
Syntax a sémantika LTL
Nechť je KS, je běh na ní. Sémantika LTL je definována:
Samozřejmě můžeme využívat libovolné výrokové logické spojky. Operátory a se nazývají temporální operátory. Jejich intuitivní význam je následující (zároveň si zavedeme další syntaktické zkratky):
Říkáme, že stav splňuje formuli, pokud ji splňují všechny běhy, které v něm začínají. Pokud má formuli splňovat celý systém, musí ji splňovat všechny stavy a nebo všechny počáteční stavy (pokud jsme si je definovali).
Výše uvedená definice LTL je praktická, pro účely model checkingu. Na LTS ji můžeme definovat dvěma způsoby:
Můžeme definovat i LTL, která nemá všechny temporální operátory. Obecně se tím však snižuje vyjadřovací síla4).
LTL může vyjádřit poměrně zajímavé vlastnosti. Zde jsou některé, které se používají v praxi (podobným vlastnostem, do kterých je ještě třeba doplnit formuli, se říká „patterns“):
Zatímco LTL se zabývá jednotlivými běhy, CTL (a podobné, tak zvané branching tj. „větvící se“ logiky) zkoumají stromovou strukturu, která v jistém ohledu obsahuje všechny možné běhy. Pro účely následující definice si zavedeme značení což je množina všech běhů v Kripkeho struktuře začínající ve stavu .
Syntax a sémantika CTL
Je zde vidět, že použité operátory jsou podobné jako u LTL, jen v případě pomocí kvantifikátorů specifikujeme, jestli mají platit pro jeden nebo všechny běhy začínající v daném stavu. Formule vyžaduje, aby v jendom z následníků stavu platilo , což se velmi podobá tomu, co umožňují modální logiky (pokud se nedíváme na označení přechodů).
Definujeme ještě další syntaktické zkratky, jejichž význam je podobný jako u LTL:
Logika CTL nemusí být úplně nejjednodušší na pochopení, zde je obrázek stavu, jeho následníků a jejich následníků, na kterých jsou ilustrovány jednotlivé operátory, tak aby , kde, zleva doprava , , a , přičemž stavy splňující jsou černé a stavy splňující šedé.
Na LTS můžeme sémantiku CTL definovat analogicky k LTL. Podobné je to také s vyjadřovací silou operátorů.
CTL umožňuje nadefinovat podobné vlastnosti jako LTL, i když s několika rozdíly.
Výše bylo zmíněno, že existují vlastnosti, které se dají vyjádřit pomocí LTL a nedají pomocí LTL a naopak. Co to znamená? Každá formule jednoznačně určuje třídu modelů, což jsou ty modely, které ji splňují. Zřejmě tedy existují třídy modelů, které se dají definovat pomocí LTL, ale ne pomocí CTL (a napopak). Formálně:
Expresivita logik
Platí, že a . Dokázat takové tvrzení je značně netriviální, už z výše uvedené definice. My si zde ukážeme, že CTL formule nemá eqvivalent v LTL.
Vezměme si následující dva systémy s počátečním stavem a dvojicí atomických propozic a :
Oba systémy produkují stejné běhy z počátečního stavu: , z tohoto důvodu nejdou rozlišit pomocí LTL, protože formule LTL se vyjadřují o bězích. Přitom počáteční stav levého systému nesplňuje formuli (pokud se dostanu do stavu označeného vlevo dole, už se nemůžu dostat do stavu označeného ), zatímco počáteční stav pravého systému ji splňuje. Z toho důvodu . Je z toho také vidět, že formule , která by intuitivně měla vyjadřovat, že se vždy můžu dostat do stavu označeného , se nechová tak, jak bychom čekali – v pravém systému, který ji zřejmě splňuje, lze provést nekonečný běh , kdy se do stavu vůbec nedostanu. Oproti tomu LTL formule není tímto systémem splněna a tím pádem se více blíží vlastnosti „vždy se můžu dostat do stavu “.
Některé formule mají LTL a CTL společné, například má stejný význam jako . Z toho by se mohlo zdát, že CTL formule vzniknou doplněním áček do CTL formulí. Není tomu ale tak, například formule a nejsou stejné. To lze ukázat na následujícím modelu (kde „!p“ symbolizuje ):
Ten produkuje běhy , tedy zřejmě splňuje . Podívejme se na platnost formule . Nejprve její sémantika. Tato formule požaduje, aby v každém běhu začínajícím v počátečním stavu byl jeden stav, ze kterého se můžeme dostat pouze do stavů, kde platí . Z počátečního stavu ale vede běh , ve kterém zůstáváme v počátečním stavu. Z počátečního stavu je ale dostupný i stav, ve kterém neplatí a systém nesplňuje .
Kromě LTL a CTL existuje ještě logika CTL*, která v sobě zahrnuje obě tyto logiky. Funguje tak, že má dva typy formulí – formule cesty a formule stavu:
Syntax CTL*
CTL* už je značně komplikovaná logika5).
Pravděpodobně nejdůležitější praktické využití temporálních logik je model checking což je automatická verifikační procedura, která pro daný model (KS) a formuli rozhodne, jestli model splňuje formuli.
Poznámka
Tento text model-checking popisuje pouze rámcově, protože jinak je to velmi obsáhlá kapitola. Celá procedura jak pro LTL, tak pro CTL je velmi dobře popsána ve studijních materiálech k předmětu IV113 Úvod do validace a verifikace, které jsou dostupné na http://www.fi.muni.cz/~xbarnat/IV113/index.html, konkrétně jde o slidy 06, 07, 08 a 09.
Název „model checking“ zřejmě není příliš český. Lze místo něj sice použít termín „ověřování modelu“, ale v praxi nikdo nebude vědět, o čem je řeč. Proto model checking.
LTL model checking je úzce spojen s Büchiho automaty. Büchiho automat je v zásadě nedeterministický konečný automat, který ale akceptuje místo konečných slov (pokud jejich čtení končí v akceptujícím stavu) slova nekonečná, a to tehdy, pokud při jejich čtení projde některým z akceptujících stavů nekonečněkrát. Využívá se následující pozorování:
Procedura pak funguje následovně:
K poslednímu kroku platí, že všechna akceptující běhy Büchiho automatu nejprve docestují z počátečního stavu do některého z akceptujících stavů a pak se do daného akceptujícího stavu neustále vracejí (vytvářejí „laso“). Typicky se používá algoritmus Nested Depth-First Search (zanořené hledání do hloubky), jehož složitost je lineární k velikosti Büchiho automatu6).
Složitost LTL model checkingu (daná velikostí výsledného Büchiho automatu) je v a je v PSPACE (viz 2-tei). Exponenciální složitost vůči velikosti formule je dána tím, že LTL se umí vyjadřovat mnohem stručněji než Büchiho automaty. V praxi ale není problém, protože se většinou používají pouze krátké LTL formule. Co je problém, je velikost modelu, tedy stavového prostoru (viz níže).
Poznámka: Je zřejmé, že kromě LTL je možné specifikovat vlastnosti také Büchiho automaty (v praxi se používají).
Na rozdíl od LTL model checkingu se CTL model checking provádí přímo na Kripkeho struktuře, a to tak, že se zavádí značkovací funkce , která pro každý stav určí, které z podformulí v něm platí. Ta se počítá induktivně podle struktury formule (od atomických propozic).
Zřejmě, pokud vím, ve kterých stavech platí a je jednoduché určit, kde platí , , a podobné. Trochu složitější jsou operátory a .
Platí, že (podobně jako rozepsání operátoru release u LTL). Tímto způsobem se lze zbavit nutnosti prohledávat všechny možné běhy. Pro výpočet hodnoty funkce se používá následující postup:
Časová složitost CTL model checkingu je v 7).
μ-kalkuly (existuje jich více) obohacují logiky o rekurzi, čímž značně zvyšují jejich vyjadřovací sílu. Modální μ-kalkulus je založen na Hennessyho-Milnerově logice, ale díky rekurzi má vyjadřovací sílu temporálních logik – konkrétně pokrývá CTL* a tím i LTL a CTL. Modální μ-kalkulus je zajímavý především z teoretického hlediska – množství tvrzení o temporálních logikách se typicky dokazuje na něm.
Syntax μ-kalkulu
Poznamenejme, že lze vyjádřit pomocí , ale pro naše účely si jej zadefinujeme zvlášť. Dále můžeme používat všechny spojky výrokové logiky a jako v HML.
Sémantika μ-kalkulu je definována poněkud zvláštním způsobem. Pro daný LTS každá formule definuje množinu stavů, ve kterých je platná. Operátory pak provádějí operace nad nimi.
Sémantika μ-kalkulu
Sémantika odpovídá sémantice tohoto operátoru v HML, jen na množinách stavů. Co znamenají výrazy a ? Oba dva označují řešení rekurzívní rovnice ( zřejmě obsahuje několik výskytů ), pokud bereme jako množinu stavů. přitom označuje nejmenší řešení a největší (pokud má rovnice pouze jedno řešení, jsou stejné).
Okdud se vzaly dva výše uvedené vzorce? Mějme formuli , která obsahuje . Pokud vezmeme jako proměnnou, určuje funkci . Řešení je pak jejím pevným bodem. Víme přitom, že podmnožiny je úplný svaz, pro který platí Knasterova-Tarskiho věta, která říká, že pokud je funkce na úplném svazu monotónní, její pevné body tvoří úplný svaz, jehož největší a nejmenší prvky jsou dány právě těmito vzorci 8). Valuace je zde použita pouze jako technická pomůcka a je zřejmé, že pokud výskytu ve formuli předchází nebo , je nám jedno, jaká je hodnota .
To, že označuje nejmenší a největší pevný bod můžeme využít pokud máme konečně-stavový prostor. Pokud chceme vypočítat množinu stavů splňující , začneme s prázdnou množinou a postupně na ní aplikujeme , dokud nedojdeme k pevnému bodu (podle Kleeneho věty). Podobně pro začneme od množiny všech stavů.
Poznámka: Protože Knusterova-Tarskiho věta platí pouze pro monotónní funkce, je nutné zaručit, aby pro byla monotónní. Problém zde činí negace. Proto se požaduje, aby na syntaktickém stromu byl mezi a libovolným volným výskytem (tj. který není pod jinými operátory nebo ) v sudý počet negací.
Modální μ-kalkulus je mocný nástroj, ale může být poněkud obtížně uchopitelný. Proto jsou zde uvedeny příklady vlastností:
Pokud nás nezajímají přechody, používá se modální operátory a , které znamenají „existuje následník“ a „pro všechny následníky“. Tyto operátory jsou jen syntaktické zkratky:
Pomocí tohoto zápisu můžeme vyjádřit další vlastnosti:
Modální a temporální logiky slouží k vyjádření vlastností přechodových systémů (a to buď LTS nebo KS). Významné logiky zahrnují:
Hennessyho-Milnerova logika a modální µ-kalkulus jsou zajímavé především z teoretického hlediska. V praxi se používá LTL a CTL, pro které existuje model checking, automatická procedura, která o modelu (přechodovém systému) dokáže rozhodnout, jestli splňuje formuli dané logiky.