จำลอง NFA


15

ออโตเมติก จำกัด nondeterministicเป็นเครื่องสถานะ จำกัด ที่ tuple ถูกแมปกับหลายรัฐ กล่าวคือ เราแทนที่ปกติδ : Q × Σ →การQฟังก์ชั่นการเปลี่ยนแปลงของDFAกับฟังก์ชั่นอื่นΔ : Q × Σ →การP ( Q )(sเสื้อaเสื้ออี,sYม.โอล.)δ:Q×ΣQ Δ:Q×ΣP(Q)

หากคุณรู้ว่า NFA คืออะไรคุณอาจต้องการข้ามหัวข้อถัดไป

นิยามอย่างเป็นทางการ

NFA อธิบายไว้โดยเฉพาะ

  • ชุดของอเมริกา จำกัดQ
  • ขอบเขตของสัญลักษณ์Σ
  • ฟังก์ชั่นการเปลี่ยนแปลงΔ:Q×ΣP(Q)
  • สถานะเริ่มต้นQ0Q
  • ชุดของสถานะสุดท้ายFQ

เครื่องจะเริ่มออกมาในและอ่านสตริง จำกัด ของสัญลักษณ์W Σ *สำหรับแต่ละสัญลักษณ์พร้อมกันจะใช้ฟังก์ชั่นฟังก์ชั่นการเปลี่ยนแปลงกับรัฐในปัจจุบันและเพิ่มแต่ละชุดใหม่ของรัฐถึงชุดของรัฐในปัจจุบันQ0WΣ* * * *

ท้าทาย

สำหรับความท้าทายนี้เราจะไม่สนใจเพื่อลดความซับซ้อนของมันนอกจากนี้ตัวอักษรจะเป็น (กรณีที่ต่ำกว่า) ตัวอักษรไปZและชุดของรัฐจะ{ 0 ... N }สำหรับบางคนที่ไม่ใช่เชิงลบจำนวนเต็มN สถานะเริ่มต้นจะเป็น0เสมอF a Z {0...ยังไม่มีข้อความ}ยังไม่มีข้อความ0

ป.ร. ให้คำและคำอธิบายของ NFA ให้งานของคุณคือการกำหนดทุกรัฐสุดท้ายW{a...Z}* * * *

ตัวอย่าง

พิจารณาสตริงและคำอธิบายต่อไปนี้:abaab

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

เครื่องจะเริ่มต้นใน :Q0=0

  1. อ่าน : สถานะใหม่{ 1 }a{1}
  2. อ่าน : สถานะใหม่{ 1 , 2 }{1,2}
  3. อ่าน : สถานะใหม่{ 0 }a{0}
  4. อ่าน : สถานะใหม่{ 1 }a{1}
  5. อ่าน : สถานะใหม่{ 1 , 2 }{1,2}

ดังนั้นรัฐสุดท้ายและทำให้การส่งออกจะเป็น }{1,2}

หมายเหตุ:ในขั้นตอน(2)การเปลี่ยนสถานะจะจับคู่กับเนื่องจากคำอธิบายประกอบด้วยการเปลี่ยนเป็นชุดที่ไม่ว่างเปล่าเท่านั้น2

กฎระเบียบ

การป้อนข้อมูลจะประกอบด้วยสตริงและชนิดของคำอธิบายของ NFA บางคน (โดยไม่ต้อง -transitions):ε

  • สตริงอินพุตจะเป็นองค์ประกอบของ{a...Z}* * * *
  • อินพุตที่ถูกต้อง (ไม่ จำกัด เฉพาะ):
    • รายการ / อาร์เรย์ของสิ่งอันดับ / รายการ
    • การป้อนข้อมูลแยกบรรทัดใหม่
  • คำอธิบายของ NFA จะมีการเปลี่ยนเฉพาะกับชุดที่ไม่ว่างเปล่าเป็นผลลัพธ์
    • คุณอาจย่อกฎที่มีตัวอักษรเดียวกันหากผลลัพธ์ของพวกเขาเหมือนกัน (เช่นกฎ0,'a',[1,2]และ0,'b',[1,2]อาจใช้ตัวย่อ0,"ab",[1,2]
    • คุณอาจแยกกฎแต่ละข้อออก (เช่นกฎ0,'a',[1,2]สามารถ0,'a',[1]และ0,'a',[2])
  • คุณอาจเลือกตัวอักษรตัวพิมพ์ใหญ่ถ้าคุณต้องการ
  • คุณอาจใช้จำนวนสถานะเป็นอินพุต
  • คุณอาจสมมติว่ามีการเรียงลำดับของอินพุต (เช่น. เรียงลำดับโดยรัฐหรือสัญลักษณ์)

เอาต์พุตจะเป็นรายการ / set / new-line ที่คั่นด้วยเอาต์พุตอื่น ๆ ของสถานะสุดท้าย

  • คำสั่งไม่สำคัญ
  • ไม่ซ้ำกัน (เนื่องจากเป็นชุด)

กรณีทดสอบ

ตัวอย่างเหล่านี้จะอยู่ในรูปแบบdescription word -> statesที่descriptionเป็นรายการของ tuples (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
นี่นำความทรงจำที่น่ากลัวกลับมาจากหลักสูตรออโตเมต
Don Thousand

เราสามารถรับอินพุตด้วยแต่ละบรรทัดสำหรับแต่ละสถานะใหม่เช่นนี้เป็นตัวอย่างการทำงานได้หรือไม่?
ovs

@ovs: แน่นอนไปเลย!
ბიმო

คำตอบ:


7

Haskell , 66 ไบต์

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

ลองออนไลน์!


คุณจะได้รับการกำจัดของการนำเข้าสำหรับnubถ้าคุณถือว่ารัฐจะเป็น[Int]แล้วคุณสามารถใช้ตรวจสอบแต่ละ[0..]ที่มี จำกัด : 60 ไบต์
ბიმო

@BWO iterates นี้มากกว่าทุกInts และมากกว่ารัฐในปัจจุบันทั้งหมดและดังนั้นจึงยังคงผลิตรัฐที่ซ้ำกัน ตัวอย่าง (เปลี่ยน[0..]เป็น[0..3]เพื่อวัตถุประสงค์ในการทดสอบ แต่สิ่งนี้ไม่ควรสร้างความแตกต่างใช่มั้ย)
ovs

ใช่ไม่แน่ใจว่าสิ่งที่ฉันคิด .. ไม่เป็นไร ..
ბიმო

4

Brachylogขนาด 42 ไบต์

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

อินพุตเป็น [สตริง, nfa] โดยที่ nfa เป็นรายการของการเปลี่ยนสถานะ [สถานะเริ่มต้นจดหมายรัฐใหม่เป็นรายการ]

คำอธิบาย

,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

ลองออนไลน์!


4

Brachylog v2, 31 ไบต์

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

ลองออนไลน์! ( หรือด้วยตัวอย่างที่ซับซ้อนกว่า )

Brachylog เป็นปัญหาที่ดีมากในเรื่องนี้และเป็นปัญหาที่ต้องแยกอินพุตและเอาต์พุตออกเป็นสองส่วน เกือบทั้งหมดของโปรแกรมนี้เป็นเพียงการประปา

รูปแบบอินพุตเป็นรายการที่มีสององค์ประกอบ: ส่วนแรกคือรายการการเปลี่ยนสถานะ ( [oldState, symbol, newState]) และรายการที่สองคือรายการสัญลักษณ์ ตอนแรกฉันวางแผนว่าโปรแกรมนี้จะทำงานกับรหัสอักขระสำหรับสัญลักษณ์ (เนื่องจากการจัดการสตริงของ Brachylog อาจเป็นเรื่องแปลก ๆ ในบางครั้ง) แต่ปรากฎว่าตัวอักษรนั้นทำงานเช่นกัน (แม้ว่าคุณจะต้องเขียนสตริงอินพุตเป็นรายการของตัวละครไม่ใช่ สตริง). หากคู่สัญลักษณ์สถานะสามารถเปลี่ยนเป็นหลายสถานะที่แตกต่างกันคุณเขียนช่วงการเปลี่ยนภาพหลายรายการเพื่อจัดการกับสิ่งนั้น

คำอธิบาย

{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.

การติดตามสิ่งนี้อาจทำได้ง่ายกว่าโดยดูว่าโปรแกรมบางเวอร์ชันจะผลิตอะไร การใช้อินพุตต่อไปนี้ในแต่ละครั้ง:

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

เราสามารถสังเกตผลลัพธ์ของคำนำหน้าบางส่วนของโปรแกรมนี้:

[[[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]]

สำหรับตัวอย่างแรกที่นี่Lเป็นองค์ประกอบที่ไม่รู้จักในขั้นต้น แต่เมื่อเราทำการแปลงผ่าน\Brachylog ตระหนักว่ามีความเป็นไปได้เพียงอย่างเดียวคือรายการที่มีความยาวเท่ากับอินพุต ตัวอย่างสุดท้ายที่นี่คือ nondeterministic; เรากำลังสร้างแบบจำลอง nondeterminism ใน NFA โดยใช้ nondeterminism ใน Brachylog เอง

การปรับปรุงที่เป็นไปได้

บางส่วนของไวยากรณ์ที่นี่เช่น↔,0↔และโดยเฉพาะอย่างยิ่งกับH&hg;Hz{…ᵈ}ᵐเป็น clunky ค่อนข้าง มันคงไม่ทำให้ฉันประหลาดใจถ้ามีคำพูดที่ซ้ำซากจำเจ

{∋ᵈ}ᵐอยู่ในโครงสร้างของตัวเองที่ค่อนข้างน่าสงสัย - คุณคาดว่าจะสามารถเขียนได้∋ᵈᵐ- แต่มันไม่ได้แยกวิเคราะห์ด้วยเหตุผลบางอย่าง


∋ᵈᵐไม่ได้แยกวิเคราะห์เพราะมีการใช้ชื่อเมตา - เครดิคหลายตัวในทางทฤษฎี (ถ้าเราหมดความเป็นไปได้ของสัญลักษณ์เดียว) ในทางปฏิบัติมันไม่ได้ใช้ในปัจจุบัน
ทำให้เสียชีวิต

3

Python 3, 103 80 ไบต์

ขอบคุณ @BWO

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

ความเข้าใจของรายการ "ฉลาด" ก่อนหน้า (103 ไบต์):

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

ความอัปยศที่หลาม 3 ขาดreduce.. แต่ใช้การเรียกซ้ำและชุดที่แท้จริงยังคงนำคุณลงไป80 ไบต์
ბიმო

@BWO ดีขอบคุณ haha ​​btw ด้านบนเป็นตัวอย่างโค้ดไพ ธ อนที่ฉันชื่นชอบใหม่ที่จะแสดง ... ความเข้าใจในรายการยักษ์บรรทัดเดียวทำให้ฉันสนุกกว่าที่ควร
Quintec

ฉันคิดว่าคุณสามารถบันทึก 2 ไบต์โดยการแทนที่ด้วยif''<f if f
Chas Brown

@Chas Brown ที่ล้มเหลวหาก f เป็นค่าที่ผิดพลาดเช่นสตริงว่าง
Quintec

ที่จริงแล้วฉันกำลังพูดอะไรไม่สนใจเลย
Quintec


3

R , 81 ไบต์

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

ลองออนไลน์!

Reduceคำตอบที่ตรงไปตรงมาใช้ นำกฎสามเวกเตอร์ที่เรียกว่าstate, symbol, new-statesa,b,e

กฎจะแยกกัน (เช่นกฎ0,'a',[1,2]คือ0,'a',1และ0,'a',2)



2

ทำความสะอาด , 68 ไบต์

อันนี้ขึ้นอยู่กับโซลูชั่น Haskell ของ ovs จะสั้นกว่าวิธีเริ่มต้นของฉันเล็กน้อย

ตอนนี้มีสายรัดทดสอบ

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

ลองออนไลน์!


1
@BWO เพิ่มสายรัดทดสอบ
Οurous

1

ถ่านขนาด 44 ไบต์

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

ลองออนไลน์! การเชื่อมโยงคือการใช้รหัสเวอร์ชันอย่างละเอียด คำอธิบาย:

⊞υ⁰

กด0ไปที่รายการว่างที่กำหนดไว้ล่วงหน้าเพื่อตั้งค่าสถานะเริ่มต้นเป็น{0}.

Fη«

วนซ้ำอินพุต

≔υζ

คัดลอกสถานะ

≔⟦⟧υ

รีเซ็ตสถานะ

Fζ

วนรอบสำเนาของรัฐ

Fθ

วนซ้ำรายการ NFA

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

หากรายการตรงกันดังนั้น ...

F§λ²

... วนรอบสถานะใหม่ ...

¿¬№υμ

.... หากพวกเขาไม่ได้อยู่ในรายการ ...

⊞υμ»

... เพิ่มไปยังรายการ

Iυ

ส่งรายการสถานะไปยังสตริงสำหรับเอาต์พุตโดยนัยบนบรรทัดแยก



1

Japt , 31 ไบต์

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

ลองมัน!

บันทึก 2 ไบต์ด้วยการใช้ความสามารถของ Japt ที่ดีกว่าในการสร้างฟังก์ชันโดยปริยายจากอินพุตบางส่วน

คำอธิบาย:

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

รหัส "เริ่มต้นสถานะ" ใหม่สามารถใช้รายละเอียดได้อีกเล็กน้อย Japt เริ่มต้นWที่ 0 หากมีน้อยกว่า 3 อินพุตดังนั้นในการรันครั้งแรก[W]คือ[0]และc"แบน" อาเรย์ [0]แบนแล้วตามที่ได้รับดังนั้นจึงไม่มีการเปลี่ยนแปลง วิ่งตามมามีค่าแตกต่างกันเช่นW [1,2]ในกรณีนั้น[W]จะกลาย[[1,2]]เป็นอาร์เรย์องค์ประกอบเดียวที่องค์ประกอบนั้นเป็นอาร์เรย์ คราวนี้cunwraps [1,2]ที่และได้รับกลับไป ดังนั้นในการทำงานครั้งแรกมันและวิ่งตามมาก็W=[0]W=W

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.