Eindige automaat
Een eindige automaat (Engels finite state machine of finite automaton) is een rekenmodel van een primitieve computer. Hij bestaat uit een aantal toestanden en een aantal overgangen en kan een aangeboden woord accepteren of verwerpen.
Voorbeeld
Informeel beschrijven we een eindige automaat met een toestandsdiagram:
De automaat bestaat uit toestanden. In de figuur zijn dat drie ronde toestanden q0, q1 en q2. Tussen deze toestanden lopen overgangen, dat zijn de pijlen. Verder moet de automaat een begintoestand hebben, dat is toestand q0. De begintoestand wordt vaak weergegeven met een pijl die erheen wijst en die niet uit een andere toestand komt. Daarnaast heeft een automaat meestal een eindtoestand. Die tekenen we met een dubbele lijn, dus in de figuur is dat toestand q2.
Een automaat die zo is opgebouwd, accepteert bepaalde woorden. We geven woorden aan de automaat en de automaat probeert ze te accepteren. Als hij het woord accepteert, antwoordt de automaat JA, anders antwoordt hij NEE. Onze automaat probeert woorden te accepteren die uit de letters “a, b, c” bestaan, dus we kunnen proberen het woord “abbc” te accepteren.
We beginnen in de begintoestand q0 en de invoer is het woord “abbc”. Vanaf nu volgen we de pijlen.
We lezen het woord zoals gewoonlijk van links naar rechts, dus als eerste nemen we het symbool “a”. De pijl voor invoer “a” gaat naar toestand q1, dus daar gaan we naartoe en we halen het symbool “a” van het woord af. De invoer is nu het woord “bbc”:
De pijl voor invoer “b” wijst terug naar knoop q1. We halen weer de eerste letter weg en de invoer is nu het woord “bc”. We blijven opnieuw in toestand q1. Tot slot is de invoer het woord “c”. Vanuit toestand q1 stuurt de pijl voor invoer “c” ons naar toestand q2.
We hebben alle letters van het invoerwoord opgebruikt en we zitten in toestand q2, een eindtoestand. Deze eindige automaat accepteert dus het woord “abbc”.
Als we aan het einde niet in een accepterende toestand zouden zitten, zou de automaat het woord niet accepteren. De automaat accepteert een woord ook niet als we in een bepaalde toestand nergens heen kunnen. Bij de invoer “ab” komen we bijvoorbeeld in toestand q1 terecht en daar blijven we steken — de automaat accepteert zo'n woord niet. Als we het woord “aabbc” testen, hebben we weer pech, want uit toestand q1 vertrekt geen pijl voor de letter “a”.
Een eindige automaat dient dus om een bepaalde verzameling woorden te herkennen. In de praktijk zouden we een automaat bijvoorbeeld kunnen gebruiken om te controleren of een invoerwoord een geldig e-mailadres is.
Definitie van een eindige automaat
De voorgaande intuïtieve voorstelling van wat een eindige automaat is, moeten we formaliseren, zodat we beter met automaten kunnen werken.
We zeggen dat een eindige (deterministische) automaat een vijftal ⟨Q, Σ, δ, q0, F⟩ is, waarbij
- Q een eindige verzameling toestanden is,
- Σ (hoofdletter sigma) het alfabet is (een eindige verzameling symbolen/letters),
- δ: Q × Σ ⟶ Q de overgangsfunctie is,
- q0 ∈ Q de begintoestand is,
- F ⊆ Q de verzameling eindtoestanden (accepterende toestanden) is.
Als we teruggaan naar de vorige automaat,
dan kunnen we zeggen dat de verzameling toestanden Q uit drie toestanden bestaat: Q = {q0, q1, q2}. Het alfabet Σ bevat de letters waarmee we woorden kunnen vormen die de automaat vervolgens accepteert of verwerpt. Hier is dat waarschijnlijk het alfabet Σ= {a, b, c}, maar het mag ook een willekeurige bovenverzameling zijn. De begintoestand q0 is toestand q0, daar verandert niets aan. De verzameling eindtoestanden bevat bij deze automaat maar één toestand: F = {q2}.
Met de overgangsfunctie bedoelen we dan die drie pijlen met letters. Als de notatie δ: Q × Σ ⟶ Q je in de war brengt: die betekent alleen dat δ een functie is (of beter gezegd een afbeelding) die twee argumenten neemt: een toestand uit Q en een letter uit Σ. Na aanroep geeft de functie een nieuwe toestand terug. Onze overgangsfunctie zouden we met een tabel zo kunnen definiëren:
Als we dus δ(q1, c) aanroepen, passen we de derde rij toe en antwoordt de functie met toestand q2 — net als het diagram. Als we in toestand q1 zitten en de invoer is de letter “c”, dan komen we in toestand q2 terecht. Voordat we formeel definiëren wat het betekent dat een automaat een woord accepteert, gebruiken we het intuïtieve begrip en laten we nog een paar voorbeelden zien.
Nog meer voorbeelden
-
Maak een automaat die werkt over het binaire alfabet, dus Σ= {0, 1}, en alleen woorden accepteert die op een één eindigen. Hij accepteert bijvoorbeeld de woorden 1, 01, 000001, 0101011.
Onze automaat heeft twee toestanden — de begintoestand q0 en de eindtoestand q1. Zodra de invoer het cijfer 1 is, gaan we naar de eindtoestand q1 en blijven we daar. Is de invoer daarentegen het cijfer 0, dan gaan we naar de niet-eindtoestand q0 en blijven we ook daar.
-
Construeer een automaat over het binaire alfabet die alleen woorden accepteert waarvan de eerste letter verschilt van de laatste letter.
De automaat splitst zich meteen in de eerste stap in twee “deelautomaten”. Als het woord met een nul begint, gaat de automaat het linkerdeel in en blijft daar; begint het met een één, dan gaat hij naar het rechterdeel. Daarna is het standaard: als we in het linkerdeel zitten en de invoer is 1, gaan we naar de eindtoestand en blijven we daar. Is de invoer 0, dan gaan we naar toestand q1, die geen eindtoestand is.
In tegenstelling tot de vorige automaten heeft deze automaat meer eindtoestanden, namelijk F = {q3, q4}.
-
Construeer een automaat over het binaire alfabet die alleen woorden accepteert die geen twee nullen achter elkaar bevatten.
Deze automaat is om twee redenen interessant. De eerste is dat hij het lege woord accepteert. We kunnen het lege woord aan de automaat geven en de automaat accepteert het als de begintoestand tegelijk een eindtoestand is, en dat is hier het geval. Omdat het lege woord een woord is dat geen twee nullen achter elkaar bevat, is dat precies goed. De tweede bijzonderheid is dat bij deze automaat alle toestanden eindtoestanden zijn. De automaat accepteert een woord dan alleen niet als er uit een toestand geen overgang vertrekt. Dat gebeurt in toestand q1, die geen overgang voor 0 heeft, want dan zou het woord twee nullen achter elkaar bevatten.
-
Construeer een automaat over het alfabet {-,+,.,0,1,…,9} die alleen woorden accepteert die een getal voorstellen. Dat betekent: een geheel getal zoals 2, 548, 98263, of een decimaal getal zoals 5584.48, 3.14, en beide ook met een minteken als negatief getal -2, -548, -3.14, en ook met een expliciet plusteken, dus +2, +548, +3.14. Tegelijk moeten we het getal 0.123 ook kunnen schrijven als .123 (zonder die nul vooraan), inclusief beide tekens. Hier gebruiken we, zoals in programmeertalen, een punt als decimaalteken. We voeren een hulpnotatie in: in plaats van tien overgangen voor tien cijfers uit te schrijven, gebruiken we het symbool N.
-
Construeer een automaat over het binaire alfabet die alleen woorden accepteert van de vorm 0n1n, dat wil zeggen: woorden die beginnen met een bepaald aantal nullen, gevolgd door evenveel enen. Voorbeelden van zulke woorden zijn 0011, 00001111, 01.
Zo'n automaat kan niet worden gebouwd, omdat we het aantal nullen nergens kunnen “onthouden”. We zouden meerdere “deelautomaten” moeten maken, net als in het tweede voorbeeld, maar het zouden er oneindig veel moeten zijn, voor elke waarde van n één.
Formalisering van de berekening van een automaat
We hebben de eindige automaat zelf al formeel gedefinieerd. Nu moeten we nog definiëren wat zo'n automaat eigenlijk doet, dus we definiëren de berekening van een automaat.
Configuratie van een automaat: we zeggen dat een paar ⟨q, w⟩ ∈ Q × Σ∗ een configuratie van de automaat is, waarbij q de huidige toestand is waarin de automaat zich bevindt en w het nog niet gelezen deel van het woord. Σ∗ is de afsluiting van het alfabet Σ, de verzameling van alle woorden die uit de letters van het alfabet Σ kunnen worden samengesteld. Het lege woord, dat we aangeven met ε, hoort ook bij de afsluiting.
Als we een automaat ⟨Q, Σ, δ, q0, F⟩ hebben en een woord w proberen te accepteren, dan bevindt de automaat zich in de beginconfiguratie ⟨q0, w⟩. Als we teruggaan naar de automaat
en het woord w = abbc willen accepteren, dan is de beginconfiguratie ⟨q0, abbc⟩.
Een rekenstap definiëren we als een relatie ↦ tussen de verzamelingen (Q × Σ∗) × (Q × Σ∗), dus tussen configuraties van de automaat. Laat w = w0w1… wn het nog niet gelezen deel van het woord w voorstellen. Dan zeggen we dat de paren ⟨q1, w0w1… wn⟩ en ⟨q2, w1… wn⟩ in de relatie ↦ staan, wat we noteren als
dan en slechts dan als δ(q1, w0) = q2. Terug naar ons voorbeeld: de beginconfiguratie is ⟨q0, abbc⟩. Uit het diagram zien we dat we bij invoer “a” naar toestand q1 kunnen gaan. We kunnen dus schrijven
want er geldt δ(q0, a) = q1. Daarmee hebben we één rekenstap gedaan — we hebben gekeken naar welke toestand we bij de gegeven invoer (= de eerste letter van het nog niet gelezen deel van het woord) moeten gaan, zijn daarheen gegaan en hebben de eerste letter van het nog niet gelezen deel van het woord verwijderd. Zo hebben we een nieuwe configuratie gekregen.
De reflexieve en transitieve afsluiting van de relatie rekenstap noteren we als ↦ ∗. Als we dus K1 ↦ ∗ K2 schrijven, waarbij K1, K2 configuraties van de automaat zijn, betekent dat dat we vanuit configuratie K1 via een aantal rekenstappen in configuratie K2 kunnen komen, oftewel er bestaat een eindige rij configuraties zodat:
In onze automaat geldt bijvoorbeeld ⟨q0, abbc⟩ ↦ ∗ ⟨q1,bc⟩, want na twee rekenstappen houden we het woord “bc” over en blijven we in toestand q1. Er bestaat dus de volgende rij configuraties:
De automaat accepteert het woord w dan en slechts dan als er een qf ∈ F bestaat zodat
en toestand q2 is een eindtoestand, q2 ∈ F.
De taal die door een automaat wordt geaccepteerd is de verzameling van alle woorden die de automaat accepteert. De taal van een automaat A noteren we als L(A). Er geldt dus L(A) ⊆ Σ∗ en
Een reguliere taal is een taal die door een of andere eindige automaat wordt geaccepteerd.
Twee eindige automaten zijn equivalent als ze dezelfde taal accepteren. Dus automaten A1 en A2 zijn equivalent als L(A1) = L(A2).
Bronnen
Hoofdstukken: Eindige automaat, Totale automaat, Niet-deterministische eindige automaat, Simulatie van een niet-deterministische automaat, Omzetting van NFA naar DFA