Lekce - Automaty a regularní výrazy Evropská unie Evropský sociální fond Praha & EU: Investujeme do vaší budoucnosti
Automat Hrací skřínka, Leopold Aucac Aine, Paris
Řídicí automat typu Moore M = < X, S=Sz ∪ Sm, Z, ω, δ, S0 > Z Následující stav S* Sm Sz * δ P a m ě ť ω Xt Vzorkování, měření vstupů Zápis výstupů X vnitřní proměnné automatu Zt
Definice konečného automatu FSM – Finite State Machine Uspořádaná šestice M = < X, S, Z, ω, δ, s0 > X - konečná množina všech vstupních vektorů Z - konečná množina všech výstupních vektorů S - konečná množina všech vnitřních stavů δ - přechodová funkce - zobrazení δ: X x S -> S ω - výstupní funkce - zobrazení ω: ω: S -> Z (Moore) ω: X x S -> Z (Mealy) s0 - počáteční stav S0 S
Příklad: Synchronní kódový zámek Odemkne, pokud vstup začíná: 0011, jinak ne. Generuje výstup A (Accepted=přijato) ve stavu Q5 Q1 1 Q2 Q3 Q4 A QE 0,1 Accepted Start Takový automat se někdy nazývá konečný akceptor, nebo rozpoznávací či klasifikační automat (Finite State Acceptor or Acceptor Finite State Machine)
Příklad2: Synchronní kódový zámek Chceme nyní odemknout, pokud vstupní posloupnost začíná 00 a končí 11 1 A B C D E
Příklad: Synchronní kódový zámek NFA – Nondeterministic Finite Automat/Acceptor 0, 1 1 Nedeterministický přechod A B C D E 1 A B C D E DFA – Deterministic Finite Automat/Acceptor
NFA- animace 1/2 NFA – Nondeterministic Finite Automat/Acceptor 0, 1 1 Nedeterministický přechod A B C D E 1 1 1 stack stack backtracking
NFA – animace 2/2 NFA – Nondeterministic Finite Automat/Acceptor 0, 1 1 Nedeterministický přechod A B C D E Accepted 1 1 1 stack
Nedeterministické chování není náhodné Deterministické: f(1) → 1 vždy Náhodné: f(1) → 1 v 50% případů, f(1) → 2 v ostatních situacích Nedeterministické chování f(1) → 1 nebo f(1) → 2, ale nepovíme, kdy tomu tak bude. Nedeterministické chování může vypadat deterministicky, náhodně, nebo i hůře
Definice konečného akceptoru Uspořádaná pětice M = < X, S, δ, s0, F > X - konečná množina všech vstupních vektorů S - konečná množina všech vnitřních stavů δ - přechodová funkce pro DFA - zobrazení δ: X x S -> S pro NFA – zobrazení δ: {X + ε} x S -> množina S, kde ε je prázdný vstup s0 - počáteční stav s0 S F – množina (i prázdná) koncových stavů F S
DFA versus NFA NFA se dají mnohem rychleji sestavit, ale obtížněji se prochází jejich stavovým diagramem – musíme si pamatovat stavy a případně se vracet. NFA s více koncovými stavy lze vždy převést na NFA s jedním koncovým stavem. NFA lze vždy převést na DFA, ale odpovídající DFA reprezentace může mít exponenciální nárůst počtu stavů nebo přechodů.
Jakákoliv posloupnost a b končící a b NFA a DFA Jakákoliv posloupnost a b končící a b C A B b a NFA a,b A A,B A,C b a DFA b a a b
Jazyky The Tower of Babel, Pieter Brueghel, c. 1563, Kunsthistorisches Museum, Vienna
Automaty rozpoznávají jazyk Abeceda (Alphabet) – konečná množina znaků Slovo (String) – konečná posloupnost znaku – může být prázdná e, (prázdné slovo se v některých textech označuje i jako l) Jazyk (Language) – množina, případně i nekonečná, všech slov utvořených z abecedy – množina může být i prázdný { }, tj. prázdný jazyk.
Předpokládejme S = {a, b, c}, pak lze z S utvořit například jazyky: Příklady jazyků Předpokládejme S = {a, b, c}, pak lze z S utvořit například jazyky: {aa,ab,ac,bb,bc,cc} {ab,abc,abcc,abccc,. . .} { e } { } {a, b, c, e}
Regulární jazyky jsou jazyky rozpoznávané pomocí NFA nebo DFA. Akceptory, které rozpoznávají regulární jazyky, se popisují regulárními výrazy. Java, PHP, Python, C# a další, implementují regulární výrazy zpravidla pomocí NFA, která se dá rychleji sestavit.
Příklady jazyků a jejich DFA
Sjednocení (Union) jazyků
Příklad sjednocení
Spojení (Concatenation)
Příklad spojení
Operace * (Kleene star)
Příklad *
Příklad na doplněk jazyka Fneg = S-F , slovy: invertujeme koncové stavy
Regulární výrazy http://www.dotnetcoders.com/web/Learning/Regex/default.aspx
Příklad: Automat → regulární výraz 1/5 2 3 4 5 6 7 d b c 1 2 3 4 5 6 7 d [abc] a b [bc] [abc] - jeden znak ze seznamu znaků. V uvedeném příkladu jde o znak a nebo b nebo c.
Příklad: Automat → regulární výraz 2/5 [abc] d a d 1 2 3 4 5 d b [bc] 6 7 3 4 5 d[abc]d d a b[bc]d
Příklad: Automat → regulární výraz 3/5 4 5 d[abc]d d a b[bc]d 3 4 5 d[abc]d d a b[bc]da b(b|c)da
Příklad: Automat → regulární výraz 4/5 3 4 5 d[abc]d d a b[bc]da 3 4 5 d[abc]d a (b[bc]da)*d
Příklad: Automat → regulární výraz 5/5 3 4 5 d[abc]d a (b[bc]da)*d 5 d[abc]da(b[bc]da)*d * - 0 nebo více znaků ze seznamu. V uvedeném příkladu jde o skupinu (b[bc]da)
Příklad: jazyk W = {anbn | n>0} Neregulární jazyky Pro neregulární jazyky nelze navrhnout NFA nebo DFA. Nelze je ani popsat regulárním výrazem. Příklad: jazyk W = {anbn | n>0}
Regulární výrazy: Metacharacters Začátečníkům pomůže knihovna regulárních výrazů http://regexlib.com/ Některé "character-class" metacharacters \d – libovolné číslo \D – nečíselný znak \w – libovolný znak slova \W – neslovní znak \s – oddělovač "whitespace" \S – není "whitespace" Příklad \d\d\d\s nalezne: "123 456"
Některé uživatelské znaky . Jeden znak s výjimkou konce řádku "newline". Např. a.a určuje aea, aia, aca, and a a [XY] Jeden znak ze seznamu znaků. V uvedeném příkladu jde o znak X nebo Y [A-Z] Jeden znak z rozsahu od A do Z (v příkladu pouze velká písmena). [A-Za-z] Jeden znak, malá nebo velká písmena A až Z [^AB] Jeden znak různý od A nebo B
Modifikátory výrazu \ ^ $ Následující znak je literal, ne "metacharacter" ^ Následující výraz se musí se objevit na začátku textu $ Následující výraz se musí objevit na konci textu "^Kolo" nalezne "Kolohnát", ale nikoliv "Moje Kolo" "stroj$" matches "Nástroj", ale ne "stroje"
Kvantifikátory * + ? {n} {n,} {n,m} () Určuje 0 or více výskytů předchozího + Určuje 1 or více výskytů předchozího ? Určuje 0 or 1 výskytů předchozího {n} Určuje přesně n výskytů předchozího {n,} Určuje nejméně n výskytů {n,m} Určuje nejméně n, ale maximálně m výskytů () Označení skupiny pro kvantifikátor, chceme-li, aby se vztahoval na více prvků
Jaká je správná odpověď?
Ukázka programu v |Java import java.util.regex.Matcher; import java.util.regex.Pattern; public class DateMatcher { public DateMatcher() { String aDate = "date: 12-15-2003"; Pattern datePattern = Pattern.compile( "date: (\\d{2})-(\\d{2})-(\\d{4})"); Matcher dateMatcher = datePattern.matcher(aDate); if (dateMatcher.find()) { System.out.println("Month is: " + dateMatcher.group(1)); System.out.println("Day is: " + dateMatcher.group(2)); System.out.println("Year is: " + dateMatcher.group(3)); } } public static void main(String[] args) { new DateMatcher(); } }
Podmnožinu regulárních výrazů umí i MS-Word Regulární výrazy se skrývají pod zástupnými znaky Nabídku operátorů najdete pod Speciální