def nedeterministička_konkatenacija(N1, N2): if not N1.stanja.isdisjoint(N2.stanja): N1 = označi(N1, '3') N2 = označi(N2, '4') Q1, Σ1, Δ1, q1, F1 = petorka(N1) Q2, Σ2, Δ2, q2, F2 = petorka(N2) assert Σ1 == Σ2 Q = disjunktna_unija(Q1, Q2) Δ = Δ1 | Δ2 | {(p1, ε, q2) for p1 in F1} return NedeterminističkiKonačniAutomat.definicija(Q, Σ1, Δ, q1, F2)
def nedeterministička_unija(N1, N2): if not N1.stanja.isdisjoint(N2.stanja): N1 = označi(N1, '1') N2 = označi(N2, '2') q0 = novo('q0', N1.stanja | N2.stanja) Q1, Σ1, Δ1, q1, F1 = petorka(N1) Q2, Σ2, Δ2, q2, F2 = petorka(N2) assert Σ1 == Σ2 Q = disjunktna_unija(Q1, Q2, {q0}) F = disjunktna_unija(F1, F2) Δ = Δ1 | Δ2 | {(q0, ε, q1), (q0, ε, q2)} return NedeterminističkiKonačniAutomat.definicija(Q, Σ1, Δ, q0, F)
class NedeterminističkiKonačniAutomat(types.SimpleNamespace): @classmethod def definicija(klasa, stanja, abeceda, prijelaz, početno, završna): assert abeceda and početno in stanja and završna <= stanja assert relacija(prijelaz, stanja, ε_proširenje(abeceda), stanja) return klasa(**locals()) @classmethod def funkcijska_definicija(klasa, stanja, abeceda, funkcija_prijelaza, početno, završna): prijelaz = set(relacija_iz_funkcije(funkcija_prijelaza)) return klasa.definicija(stanja, abeceda, prijelaz, početno, završna) @classmethod def iz_tablice(klasa, tablica): prva, *ostale = tablica.strip().splitlines() znakovi = prva.split() assert all(len(znak) == 1 for znak in znakovi) abeceda = set(znakovi) stanja, završna = set(), set() prijelaz, početno = set(), None for linija in ostale: stanje, *dolazna = linija.split() if početno is None: početno = stanje extra = len(dolazna) - len(znakovi) assert extra >= 0 if extra > 0 and dolazna[~0] == '#': del dolazna[~0] završna.add(stanje) for znak, dolazno in zip(znakovi, dolazna): for dolazno1 in filter(None, dolazno.split('/')): prijelaz.add((stanje, znak, dolazno1)) for dolazno in dolazna[len(znakovi):]: for dolazno2 in dolazno.split('/'): prijelaz.add((stanje, ε, dolazno2)) stanja.add(stanje) return klasa.definicija(stanja, abeceda, prijelaz, početno, završna) @classmethod def iz_konačnog_automata(klasa, konačni_automat): Q, Σ, δ, q0, F = petorka(konačni_automat) Δ = {(q, α, δ[q, α]) for q in Q for α in Σ} return klasa.definicija(Q, Σ, Δ, q0, F) @property def abeceda_ε(automat): return ε_proširenje(automat.abeceda) @property def funkcija_prijelaza(automat): return funkcija_iz_relacije( automat.prijelaz, automat.stanja, automat.abeceda_ε) ispiši = lambda automat: pprint.pprint(petorka(automat)) def prihvaća(automat, ulaz): δ = automat.funkcija_prijelaza moguća = ε_zatvorenje(δ, {automat.početno}) for znak in ulaz: moguća = ε_zatvorenje(δ, dolazna(δ, moguća, znak)) return not moguća.isdisjoint(automat.završna)
def označi(nka, l): Q, Σ, Δ, q0, F = petorka(nka) Ql = {označi1(q, l) for q in Q} Δl = {(označi1(p, l), α, označi1(q, l)) for p, α, q in Δ} q0l = označi1(q0, l) Fl = {označi1(q, l) for q in F} return NedeterminističkiKonačniAutomat.definicija(Ql, Σ, Δl, q0l, Fl)
def partitivna_konstrukcija(nka): Q, Σ, Δ, q0, F = petorka(nka) δ = nka.funkcija_prijelaza PQ = partitivni_skup(Q) δ_KA = {} F_KA = set() for stanje in PQ: for α in Σ: δ_KA[stanje, α] = ε_zatvorenje(δ, dolazna(δ, stanje, α)) if not stanje.isdisjoint(F): F_KA.add(stanje) q0_KA = ε_zatvorenje(δ, fset({q0})) return KonačniAutomat.definicija(PQ, Σ, δ_KA, q0_KA, F_KA)
def optimizirana_partitivna_konstrukcija(nka): Q, Σ, Δ, q0, F = petorka(nka) δ = nka.funkcija_prijelaza Q_KA = set() δ_KA = {} F_KA = set() q0_KA = ε_zatvorenje(δ, fset({q0})) red = collections.deque([q0_KA]) while red: stanje = red.popleft() if stanje not in Q_KA: for α in Σ: novo_stanje = ε_zatvorenje(δ, dolazna(δ, stanje, α)) δ_KA[stanje, α] = novo_stanje red.append(novo_stanje) Q_KA.add(stanje) if not stanje.isdisjoint(F): F_KA.add(stanje) return KonačniAutomat.definicija(Q_KA, Σ, δ_KA, q0_KA, F_KA)
def iz_konačnog_automata(klasa, konačni_automat): Q, Σ, δ, q0, F = petorka(konačni_automat) Δ = {(q, α, δ[q, α]) for q in Q for α in Σ} return klasa.definicija(Q, Σ, Δ, q0, F)
def nedeterministički_reverz(N): Q, Σ, Δ, q0, F = petorka(N) kraj = novo('qz', Q) Δ_ᴙ = {(q, α, p) for p, α, q in Δ} | {(kraj, ε, z) for z in F} return NedeterminističkiKonačniAutomat.definicija( Q | {kraj}, Σ, Δ_ᴙ, kraj, {q0})
def nedeterministička_zvijezda(N): Q, Σ, Δ, q0, F = petorka(nedeterministički_plus(N)) poč = novo('q0', Q) return NedeterminističkiKonačniAutomat.definicija( Q | {poč}, Σ, Δ | {(poč, ε, q0)}, poč, F | {poč})
def nedeterministički_plus(N): Q, Σ, Δ, q0, F = petorka(N) Δ_plus = Δ | {(p, ε, q0) for p in F} return NedeterminističkiKonačniAutomat.definicija(Q, Σ, Δ_plus, q0, F)