Bir NFA benzetimi


15

Bir nondeterministic FA tuple sonlu durum makinesi birden çok durum eşleştirilir. Yani. DFA'nın normal δ : Q × Σ Q geçiş işlevini başka bir Δ : Q × Σ P ( Q ) işleviyle değiştiriyoruz .(state,symbol)δ:Q×ΣQ Δ:Q×ΣP(Q)

Bir NFA'nın ne olduğunu biliyorsanız, sonraki bölümü atlamak isteyebilirsiniz.

Resmi tanımlama

Bir NFA benzersiz bir şekilde

  • Q sınırlı bir durum kümesi
  • Σ sonlu bir sembol seti
  • geçiş fonksiyonuΔ:Q×ΣP(Q)
  • başlangıç ​​durumuq0Q
  • bir dizi son durumFQ

Makine ile başlar ve w Σ sembollerinden oluşan sınırlı bir dizi okur , her sembol için aynı anda geçiş fonksiyonu işlevini geçerli durumla uygular ve her yeni durum kümesini geçerli durum kümesine ekler.q0wΣ

Meydan okuma

Bu meydan okuma için biz göz ardı eder ayrıca alfabe hep harfler (küçük harfle) olacaktır, bunu basitleştirmek için bir etmek z ve devletlerin kümesi olacak { 0 ... N } tamsayı olmayan bazı negatif için N . Başlangıç ​​durumu her zaman 0 olurF a z {0N}N0 .

W { az } kelimesi verildiw{az} ve NFA açıklaması, görev tüm nihai durumlarını belirlemektir.

Misal

dizesini ve aşağıdaki açıklamayı göz önünde bulundurun :abaab

state, symbol, new-states
0, 'a', [1]
1, 'a', [0]
1, 'b', [1,2]

Makine q 0 = 0 olarak başlayacakq0=0 :

  1. Bir okuma : Yeni devletler { 1 }a{1}
  2. a : yeni durumlar { 1 , 2 }b{1,2}
  3. Bir okuma : Yeni devletler { 0 }a{0}
  4. Bir okuma : Yeni devletler { 1 }a{1}
  5. a : yeni durumlar { 1 , 2 }b{1,2}

Dolayısıyla nihai durumlar ve dolayısıyla çıktı .{1,2}

Not: (2) adımında , durum eşlemelerinin 2 , açıklama sadece boş olmayan setlere geçişleri içerdiği ya geçişi.

kurallar

Giriş, bir dize ve olmadan (NFA tarifnamenin bir tür oluşacak -transitions):ϵ

  • giriş dizesi daima { az } öğesi olacaktır{az}
  • geçerli girdiler (bunlarla sınırlı değildir):
    • liste / tuples / list dizisi
    • yeni satır ayrılmış giriş
  • NFA'nın açıklaması yalnızca sonuç olarak boş olmayan kümelerle geçişler içerecektir
    • sonuçları aynıysa kuralları aynı karakterlerle kısaltabilirsiniz (örn. kurallar 0,'a',[1,2]ve 0,'b',[1,2]ile kısaltılmış olabilir)0,"ab",[1,2]
    • her kuralı ayrı alabilirsiniz (örn. kural 0,'a',[1,2]olabilir 0,'a',[1]ve 0,'a',[2])
  • isterseniz büyük harfleri seçebilirsiniz
  • durum sayısını girdi olarak alabilirsiniz
  • girişlerin bir tür sırasını varsayabilirsiniz (örn. eyalet veya semboller tarafından sıralanmıştır)

Çıktı, son durumların bir listesi / seti / yeni satır ayrılmış çıktısı vb. Olacaktır.

  • sipariş önemli değil
  • yineleme yok (bir set olduğu için)

Test senaryoları

Bu örnekler , tuples listesinin description word -> statesbulunduğu formatta olacaktır :description(state,symbol,new-states)

[]  "x" -> []
[]  "" -> [0]
[(0,'a',[1]),(1,'a',[0]),(1,'b',[1,2])]  "abaab" -> [1,2]
[(0,'a',[1]),(1,'a',[0]),(1,'b',[1,2])]  "abc" -> []
[(0,'p',[0,1]),(0,'g',[2]),(1,'c',[1]),(1,'g',[4]),(1,'p',[2]),(2,'c',[0])]  "ppcg" -> [2,4]
[(0,'f',[1]),(1,'o',[1,2]),(2,'b',[3]),(3,'a',[4]),(4,'r',[0,4])]  "foobar" -> [0,4]
[(0,'f',[1]),(1,'o',[1,2]),(2,'b',[3]),(3,'a',[4]),(4,'r',[0,4])]  "fooooooobar" -> [0,4]
[(0,'f',[1]),(1,'o',[1,2]),(2,'b',[3]),(3,'a',[4]),(4,'r',[0,4])]  "fobarfo" -> [1,2]
[(0,'f',[1]),(1,'o',[1,2]),(2,'b',[3]),(3,'a',[4]),(4,'r',[0,4])]  "foobarrf" -> [1]
[(0,'d',[1,2]),(1,'u',[2]),(2,'u',[2,3]),(2,'p',[3]),(3,'p',[3])]  "dup" -> [3]
[(0,'a',[0,2]),(0,'b',[3]),(1,'a',[1]),(1,'b',[1]),(2,'b',[1,4]),(4,'b',[2])]  "aab" -> [3,1,4]
[(0,'a',[0,2]),(0,'b',[3]),(1,'a',[1]),(1,'b',[1]),(2,'b',[1,4]),(4,'b',[2])]  "abb" -> [1,2]


3
Bu, otomat kursumdaki korkunç anıları geri getiriyor.
Don Bin

Her yeni durum için ayrı satırlarla girdi alabilir miyiz, örneğin işlenmiş örnek için bu ?
ovs

@ovs: Elbette devam edin!
ბიმო

Yanıtlar:


7

Haskell , 66 bayt

import Data.List
f d=foldl(\s c->nub[r|(y,r)<-d,g<-s,(g,c)==y])[0]

Çevrimiçi deneyin!


nubEyaletlerin olduğunu varsayarsanız ithalattan kurtulabilirsiniz [Int], o zaman [0..]sonlu olan her birini kontrol edin : 60 bayt
ბიმო

@BWO Bu, tüm Ints ve tüm mevcut durumları yineler ve bu nedenle yine de yinelenen durumlar üretir. Örnek (değişti [0..]için [0..3]test amaçlı, ama bu doğru, bir fark yaratmak gerekmez mi?)
ovs

Evet, ne düşündüğümden emin değilim ..
Boşver

4

Brachylog , 42 bayt

,0{hẸ&t|∋₁B∋IhJ&tJ&hhC∧I∋₁C∧It∋S&hb;B,S↰}ᵘ

[string, nfa] olarak girdi; burada nfa, durum geçişlerinin bir listesidir [başlangıç ​​durumu, harf, liste olarak yeni durumlar]

açıklama

,0                                              # Append 0 to the input (initial state)
  {                                      }ᵘ     # Find all unique outputs
   h                                            # if first element (string)
    Ẹ                                           #   is empty
     &t                                         #   then: return last element (current state)
       |                                        #   else:
        ∋₁B                                     #       save the state transitions in "B"
           ∋I                                   #       take one of these transitions, save in "I"
             hJ                                 #       take the initial state requirement, store in "J"
               &tJ                              #       make sure "J" is actually the current state
                  &hhC                          #       Save first char of string in C
                      ∧I∋₁C                     #       make sure the char requirement for the state transition is the current char
                           ∧It∋S                #       Make "S" equal to one of the new states
                                &hb             #       Behead the string (remove first char)
                                   ;B,S         #       Add B (the state transitions) and S (the new state)
                                       ↰        #       recur this function

Çevrimiçi deneyin!


4

Brachylog v2, 31 bayt

{b,Ȯ,Ȯ\c↔,0↔ġ₃kH&hg;Hz{∋ᵈ}ᵐtt}ᵘ

Çevrimiçi deneyin! ( veya daha karmaşık bir örnekle )

Brachylog bu tür bir problemde gerçekten iyidir ve iki ayrı giriş ve bir çıkış gerektiren problemlerde gerçekten kötüdür. Bu programın neredeyse tamamı sadece sıhhi tesisat.

Girdi biçimi iki öğe içeren bir listedir: birincisi durum geçişlerinin listesi ( [oldState, symbol, newState]) ve ikincisi sembollerin listesidir. Başlangıçta bu programı semboller için karakter kodlarıyla çalışmak üzere planladım (çünkü Brachylog'un dize kullanımı bazen biraz garip olabilir), ancak karakterlerin de işe yaradığı ortaya çıktı (giriş dizesini karakter listesi olarak değil, dizi). Bir durum sembolü çifti birden çok farklı duruma geçebiliyorsa, bununla başa çıkmak için birden fazla geçiş yazarsınız.

açıklama

{b,Ȯ,Ȯ\c↔,0↔ġ₃kH&hg;Hz{∋ᵈ}ᵐtt}ᵘ
{                            }ᵘ   Find all distinct outputs that can result from:
 b                                  taking the input minus its first element,
  ,Ȯ                                appending a singleton list (i.e. an element)
    ,Ȯ                              then appending that same element again
      \                             and transposing;
       c                            then concatenating the resulting lists,
        ↔,0↔                        prepending a 0,
            ġ₃                      grouping into blocks of 3 elements
              k                       (and discarding the last, incomplete, block),
               H&                   storing that while we
                 h                  take the first input element,
                  g  z              pair a copy of it with each element of
                   ;H                 the stored value,
                      {  }ᵐ         assert that for each resulting element
                       ∋ᵈ             its first element contains the second,
                        ᵈ ᵐ           returning the list of second elements,
                            t       then taking the last element of
                           t          the last element.

Bunu, programın bazı kısmi sürümlerinin ne üreteceğine bakarak takip etmek daha kolaydır. Her defasında aşağıdaki girdiyi kullanarak:

[[[0,97,1],[1,97,0],[1,98,1],[1,98,2]],[97,98,97,97,98]]

bu programın bazı öneklerinin çıktılarını gözlemleyebiliriz:

[[[0,97,1],[1,97,0],[1,98,1],[1,98,2]],[97,98,97,97,98]]b,Ȯ,Ȯ
[[97,98,97,97,98],L,L]

[[[0,97,1],[1,97,0],[1,98,1],[1,98,2]],[97,98,97,97,98]]b,Ȯ,Ȯ\
[[97,A,A],[98,B,B],[97,C,C],[97,D,D],[98,E,E]]

[[[0,97,1],[1,97,0],[1,98,1],[1,98,2]],[97,98,97,97,98]]b,Ȯ,Ȯ\c↔,0↔
[0,97,A,A,98,B,B,97,C,C,97,D,D,98,E,E]

[[[0,97,1],[1,97,0],[1,98,1],[1,98,2]],[97,98,97,97,98]]b,Ȯ,Ȯ\c↔,0↔ġ₃k
[[0,97,A],[A,98,B],[B,97,C],[C,97,D],[D,98,E]]

[[[0,97,1],[1,97,0],[1,98,1],[1,98,2]],[97,98,97,97,98]]b,Ȯ,Ȯ\c↔,0↔ġ₃kH&hg;Hz
[[[[0,97,1],[1,97,0],[1,98,1],[1,98,2]],[0,97,A]],
 [[[0,97,1],[1,97,0],[1,98,1],[1,98,2]],[A,98,B]],
 [[[0,97,1],[1,97,0],[1,98,1],[1,98,2]],[B,97,C]],
 [[[0,97,1],[1,97,0],[1,98,1],[1,98,2]],[C,97,D]],
 [[[0,97,1],[1,97,0],[1,98,1],[1,98,2]],[D,98,E]]]

[[[0,97,1],[1,97,0],[1,98,1],[1,98,2]],[97,98,97,97,98]]b,Ȯ,Ȯ\c↔,0↔ġ₃kH&hg;Hz{∋ᵈ}ᵐ
e.g. [[0,97,1],[1,98,1],[1,97,0],[0,97,1],[1,98,1]]

Buradaki ilk örnek Liçin başlangıçta bilinmeyen bir unsurdur, ancak onu \aktardığımızda, Brachylog tek olasılığın girişle aynı uzunlukta bir liste olduğunu fark eder. Buradaki son örnek belirsizdir; Brachylog'un kendisindeki belirsizliği kullanarak NFA'daki belirsizliği modelliyoruz.

Olası iyileştirmeler

Buradaki sözdiziminin bazıları, ↔,0↔özellikle de karışıklık gibi H&hg;Hz{…ᵈ}ᵐ, oldukça tıknaz. Bunu düzeltmenin ters bir yolu olsaydı beni şaşırtmazdı.

{∋ᵈ}ᵐkendi başına oldukça şüpheli bir yapıdır - sadece yazmayı beklersiniz ∋ᵈᵐ- ama bir sebepten dolayı ayrışmaz.


∋ᵈᵐayrıştırmaz çünkü teoride çok karakterli meta-yüklem isimlerinin kullanılabileceği şekilde uygulanır (tek sembol olasılıkları tükendiğinde). Uygulamada şu anda kullanılmamaktadır.
2018'de

3

Python 3, 103 80 bayt

@BWO sayesinde

w=lambda n,f,a={0}:w(n,f[1:],{y for(x,c,y)in n if c==f[0]and{x}&a})if''<f else a

TIO

Önceki "zarif" liste kavrama (103 bayt):

def w(a,b):
    q=[0]
    for c in b:q=[j for s in q for i in a if s in i if i[1]==c for j in i[2]]
    return q

Python 3'ün eksik olduğu için utanç reduce.. Ama özyineleme ve gerçek kümeler kullanmak sizi hala 80 bayta indirir .
ბიმო

@BWO güzel, teşekkürler, haha ​​btw yukarıdaki yeni favori örnek python kodumu göstermek için ... bir satır dev liste kavrayışları beni olması gerekenden daha fazla eğlendiriyor
Quintec

Sana değiştirerek 2 bayt kurtarabilir miyiz if''<file if f.
Chas Brown

@ F Boş bir dize gibi falsili bir değerse başarısız olan Brown
Quintec

Aslında ne diyorum, bunu görmezden
gel

3

JavaScript (ES6), 99 bayt

Girişi alır (nfa)(string). Bir Küme döndürür.

a=>g=([c,...b],s=[0])=>c?g(b,a.reduce((p,[x,y,z])=>s.includes(x)&y==c?[...p,...z]:p,[])):new Set(s)

Çevrimiçi deneyin!


3

R , 81 bayt

function(a,b,e,s)Reduce(function(A,x)unique(e[a%in%A&b==x]),el(strsplit(s,"")),0)

Çevrimiçi deneyin!

Kullanarak doğrudan cevap Reduce. state, symbol, new-statesDenilen üç vektör olarak kuralları alır a,b,e.

Kurallar ayrıdır (örn. Kural 0,'a',[1,2]olduğunu 0,'a',1ve 0,'a',2).



2

Temiz , 68 bayt

Ovs'un Haskell çözümüne dayanan bu ilk yaklaşımımdan biraz daha kısa.

şimdi bir test askısı içeriyor

import StdEnv
?d=foldl(\s c=removeDup[r\\(y,r)<-d,g<-s|(g,c)==y])[0]

Çevrimiçi deneyin!


1
@BWO Test kablo takımı eklendi
Οurous

1

Kömür , 44 bayt

⊞υ⁰Fη«≔υζ≔⟦⟧υFζFθ¿∧⁼§λ⁰κ⁼§λ¹ιF§λ²¿¬№υμ⊞υμ»Iυ

Çevrimiçi deneyin! Bağlantı, kodun ayrıntılı versiyonudur. Açıklama:

⊞υ⁰

Bas 0için açmasının durumunu ayarlamak için önceden tanımlanmış boş listeye{0}.

Fη«

Girişin üzerinden dönün.

≔υζ

Durumu kopyalayın.

≔⟦⟧υ

Durumu sıfırlayın.

Fζ

Devlet kopyasının üzerinden geçin.

Fθ

NFA girişlerinin üzerinden geçin.

¿∧⁼§λ⁰κ⁼§λ¹ι

Giriş eşleşirse, ...

F§λ²

... yeni eyaletlerin üzerinden geçip ...

¿¬№υμ

.... listede yoksa ...

⊞υμ»

... onları listeye ekleyin.

Iυ

Ayrı satırlarda örtük çıktı için durum listesini dizeye yayınlayın.



1

Japt , 31 bayt

W=[W]c;Ê?ßUÅVVf!øW føUg)mÌc):Wâ

Dene!

Japt'un bazı girdilerden örtük olarak bir işlev oluşturma yeteneğini daha iyi kullanan 2 bayt kaydedildi

Açıklama:

W=[W]c;                            Initialize the state set to [0] on the first run
       Ê?                   :Wâ    If the input is empty return the unique states; else...
             Vf!øW                 Get the transitions valid for one of the current states
                   føUg)           Of those, get the ones valid for the current character
                        mÌc)       Merge the states of the remaining transitions
         ßUÅV                      Repeat with the remaining characters as input

Yeni "durumları başlat" kodu biraz daha fazla ayrıntı kullanabilir. Japt başlatır Worada ilk çalıştırma böylece, daha az 3 giriş ise 0 [W]olduğu [0]ve c"yüksek derecede düzeltilir", bir dizi. [0]zaten olduğu kadar düz, bu yüzden değişmedi. Müteakip çalışmalarda W, örneğin farklı bir değer vardır [1,2]. Bu durumda , o öğenin bir dizi olduğu tek elemanlı bir dizi [W]haline gelir [[1,2]]. Bu sefer bunu cçözüyor ve geri dönüyor [1,2]. Böylece, ilk çalıştırmada W=[0]ve sonraki çalıştırmada W=W.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.