วิธีสร้าง DFA จากนิพจน์ทั่วไปโดยไม่ใช้ NFA


12

วัตถุประสงค์คือการสร้าง DFA จากนิพจน์ทั่วไปและการใช้ "การแปลงประสบการณ์ปกติ> NFA> การแปลง DFA" ไม่ใช่ตัวเลือก เราจะทำเช่นนั้นได้อย่างไร?

ฉันถามคำถามนี้กับอาจารย์ของเรา แต่เขาบอกฉันว่าเราสามารถใช้สัญชาตญาณและปฏิเสธที่จะให้คำอธิบายใด ๆ ดังนั้นฉันอยากถามคุณ

"exp ปกติ> NFA> การแปลง DFA" ไม่ใช่ตัวเลือกเนื่องจากการแปลงดังกล่าวใช้เวลานานในการแปลงนิพจน์ทั่วไปที่ค่อนข้างซับซ้อน ตัวอย่างเช่นสำหรับ regex "regex> NFA> DFA" ที่แน่นอนใช้เวลา 1 ชั่วโมงสำหรับมนุษย์ ฉันต้องแปลง regex เป็น DFA ในเวลาน้อยกว่า 30 นาที


2
คุณต้องระบุบริบทเพิ่มเติม คุณกำลังใช้อัลกอริธึมอะไรในการแปลนิพจน์ทั่วไป a(a|ab|ac)*a+มันอาจจะเป็นประโยชน์ในการอธิบายกระบวนการของคุณด้วยตัวอย่างเช่น คุณสามารถแปลสิ่งนั้นเป็น NDFA โดยตรงซึ่งคุณลดให้เป็น DFA หรือคุณสามารถทำให้มาตรฐานเป็นสิ่งที่แมปกับ DFA ได้ทันที
amon

คุณต้องทำมันในตัวอย่างที่เฉพาะเจาะจงไม่ว่าจะด้วยวิธีการใดหรือคุณต้องมีขั้นตอนทั่วไปเพื่อให้คอมพิวเตอร์นำไปใช้?
babou

คำตอบ:


18

เนื่องจากคุณต้องการ "แปลง regex เป็น DFA ในเวลาน้อยกว่า 30 นาที" ฉันคิดว่าคุณกำลังทำงานด้วยมือกับตัวอย่างที่ค่อนข้างเล็ก

ในกรณีนี้คุณสามารถใช้อัลกอริทึมของ Brzozowski ซึ่งคำนวณหุ่นยนต์ Nerode ของภาษาโดยตรง (ซึ่งเป็นที่ทราบกันว่ามีค่าเท่ากับหุ่นยนต์ที่กำหนดน้อยที่สุด) มันขึ้นอยู่กับการคำนวณโดยตรงของอนุพันธ์และยังใช้งานได้สำหรับการแสดงผลปกติแบบขยายที่ช่วยให้การแยกและการเติมเต็ม ข้อเสียเปรียบของอัลกอริทึมนี้คือต้องตรวจสอบความเท่าเทียมกันของนิพจน์ที่คำนวณไปพร้อมกันซึ่งเป็นกระบวนการที่มีราคาแพง แต่ในทางปฏิบัติและสำหรับตัวอย่างเล็ก ๆ มันมีประสิทธิภาพมาก[1]

บวกลบคูณหารซ้าย ให้เป็นภาษาของและให้เป็นคำ จากนั้น ภาษาจะเรียกว่าเป็นความฉลาดทางด้านซ้าย (หรือซ้ายอนุพันธ์ ) ของLLAu

u1L={vAuvL}
u1LL

หุ่นยนต์ Nerode หุ่นยนต์ Nerodeของเป็นกำหนดหุ่นยนต์ที่ ,และมีการกำหนดฟังก์ชั่นการเปลี่ยนสำหรับแต่ละโดยสูตร ระวังคำจำกัดความที่เป็นนามธรรมนี้ สถานะของแต่ละเป็นความฉลาดทางด้านซ้ายของโดยคำและด้วยเหตุนี้ภาษาของ * สถานะเริ่มต้นคือภาษาและชุดของสถานะสุดท้ายคือชุดของผลหารทางซ้ายทั้งหมดของLA(L)=(Q,A,,L,F)Q={u1LuA}F={u1LuL}aA

(u1L)a=a1(u1L)=(ua)1L
ALALLด้วยคำพูดของLL

อัลกอริทึมของ Brzozowski ให้เป็นตัวอักษร เราสามารถคำนวณหารซ้ายโดยใช้สูตรต่อไปนี้: a,b

a11=0a1b={1if a=b0if aba1(L1L2)=a1L1u1L2,a1(L1L2)=a1L1u1L2,a1(L1L2)=a1L1u1L2,a1L=(a1L)L
a1(L1L2)={(a1L1)L2si 1L1,(a1L1)L2a1L2si 1L1

ตัวอย่าง สำหรับเราได้รับอย่างต่อเนื่อง: ซึ่งให้ออโตขั้นต่ำต่อไปนี้ L=(a(ab))(ba)

11L=L=L1a1L1=(ab)(a(ab))=L2b1L1=a(ba)=L3a1L2=b(ab)(a(ab))(ab)(a(ab))=bL2L2=L4b1L2=a1L3=(ba)=L5b1L3=a1L4=a1(bL2L2)=a1L2=L4b1L4=b1(bL2L2)=L2b1L2=L2a1L5=b1L5=a(ba)=L3
หุ่นยนต์น้อยที่สุด

[1] J. Brzozowski, อนุพันธ์ของการแสดงออกปกติ, J.ACM 11 (4), 481–494, 1964

แก้ไข (5 เมษายน 2015) ฉันเพิ่งค้นพบว่าคำถามที่คล้ายกัน: อัลกอริทึมอะไรอยู่สำหรับการสร้าง DFA ที่รับรู้ภาษาที่อธิบายโดย regex ที่กำหนด? ถูกถามใน cstheory คำตอบบางส่วนแก้ไขปัญหาความซับซ้อน


คุณสามารถพูดเพิ่มเติมเกี่ยวกับความซับซ้อนของอัลกอริทึมนี้ได้หรือไม่?
babou

@babou การแปลง RE เป็น DFA นั้นเป็น PSPACE-hard ดังนั้นมันจึงเป็นเลขชี้กำลัง
jmite

นี่น่าจะเป็นคำตอบ OP เริ่มต้นด้วย "สิ่งก่อสร้างมาตรฐานผ่าน NFA ช้าเกินไป" และส่วนหนึ่งของคำตอบน่าจะเป็น "โชคไม่ดีไม่มีทางออกที่รวดเร็ว" มันยังคงเพื่อหารือเกี่ยวกับว่าที่นี่ดีกว่าการก่อสร้างมาตรฐาน (cc @jmite)
Raphael

@jmite ใช่ฉันคาดหวังไว้ เหตุผลสำหรับคำถามของฉันคือสาเหตุที่วิธีการสร้าง DFA นี้ควรได้รับการพิจารณาง่ายขึ้น (หมายเหตุ: ระบบใช้เวลาทั้งวันเพื่อแจ้งให้ฉันทราบถึง @ jmite answer)
babou

2

J.-E. Pin ให้คำตอบที่ดีกว่าในแง่ของความเป็นทางการและความสมบูรณ์ แต่ฉันคิดว่ามีบางสิ่งที่จะพูดสำหรับ "ปรีชาญาณ" ที่อาจารย์ของคุณกำลังพูดถึงอยู่

ในกรณีส่วนใหญ่สิ่งที่ง่ายที่สุดที่จะทำคือดูที่นิพจน์ปกติเข้าใจภาษาที่ยอมรับแล้วใช้ความคิดสร้างสรรค์ / ความฉลาดของคุณเพื่อสร้าง DFA ที่ยอมรับภาษานั้น

ไม่มีวิธีที่ตรงไปตรงมาในการทำสิ่งนี้นอกเหนือจากอัลกอริทึมที่คนอื่นได้ให้ แต่นี่เป็นแนวทางที่อาจเป็นประโยชน์

  1. ถามตัวเองฉันจะเขียนโปรแกรมที่ยอมรับ RE นี้โดยใช้ตัวแปรบูลีนหรือเลขจำนวนเต็มขนาดเล็กมากเท่านั้นได้หรือไม่? จากนั้นเขียนโปรแกรมนั้นและแปลงเป็น DFA ซึ่งมีสถานะสำหรับการรวมกันของค่าทั้งหมด

  2. มองหาส่วนต่าง ๆ ของนิพจน์ทั่วไปที่คุณรู้ว่าคุณสามารถยอมรับได้อย่างแน่วแน่โดยที่คุณรู้ว่า "ถ้าฉันเห็นสิ่งนี้ฉันต้องจับคู่ส่วนนี้ของ RE" จะไม่ได้มีสิ่งเหล่านี้มากมายนัก แต่การระบุชิ้นส่วนเหล่านี้สามารถแสดงชิ้นส่วนที่จะทำให้ DFA ง่ายขึ้นดังนั้นคุณสามารถใช้เวลามากขึ้นในส่วนที่ต้องใช้การกำหนด

  3. การสร้างชุดย่อยสำหรับ NFA-> DFA ไม่ใช่ความซับซ้อนของอัลกอริทึมจริง ๆ ดังนั้นถ้านี่คือการมอบหมายไม่ใช่คำถามสอบอาจเร็วกว่าที่จะเขียนโค้ดการใช้งานและให้โปรแกรมของคุณแปลง NFA เป็น DFA หากคุณใช้รหัสของคุณเองไม่ควรมีปัญหาเรื่องการแบ่งแยก

โปรดจำไว้ว่าไม่ว่าคุณจะทำอะไรเทคนิคใดก็ตามที่จะระเบิดอย่างสุดเหวี่ยงในกรณีที่เลวร้ายที่สุด (เว้นแต่คุณจะพบอัลกอริทึมแบบพหุนามสำหรับสิ่งนี้ในกรณีนี้ขอแสดงความยินดีคุณได้พิสูจน์แล้วว่าและตอนนี้คุณเป็นเศรษฐี .)P=NP=PSPACE

ลอง "มองไปข้างหน้า" ตัดมุมเมื่อคุณสามารถใช้สัญชาตญาณของคุณในสถานที่ที่อัลกอริทึมจะต้องใช้หลายขั้นตอน แต่ผลลัพธ์ของมันชัดเจน


-2

แม้ว่านี่จะไม่ใช่วิธีที่ถูกต้อง แต่ใช้งานได้ตลอดเวลา

ขั้นตอนแรก : ค้นหาสตริงที่เล็กที่สุดที่นิพจน์ทั่วไปยอมรับได้ ขั้นตอนที่สอง : วาดสถานะที่จำเป็นด้วยธุรกรรมของเครื่องตอบรับสายต่ำสุด ขั้นตอนที่สาม : สำหรับทุกรัฐให้ทำธุรกรรมตัวอักษรที่เหลือ

ตัวอย่างเช่น: นิพจน์ทั่วไป (0 + 1) * 1 "สตริงที่ลงท้ายด้วย 1" ขั้นตอนที่ 1: สตริงที่เล็กที่สุด: 1 ขั้นตอนที่ 2: สองสถานะ Q0 และ Q1 มีการทำธุรกรรม 1 จาก Q0 ถึง Q1 และ Q1 เป็นสถานะที่ยอมรับได้ ขั้นตอนที่ 3: สำหรับธุรกรรม Q0 สถานะ Q0 1 คือไปที่ Q1 ตอนนี้ทำธุรกรรม 0 ใน Q0 เอง สำหรับธุรกรรม Q1 รัฐไตรมาสที่ 1 1 จะยังคงอยู่ในไตรมาสที่ 1 และธุรกรรม 0 รายการจะไปใน Q0

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