Pushdown Automata

კომპიუტერულ მეცნიერებებში Pushdown Automata(PDA) არის მანქანის ისეთი ტიპი, რომელიც იყენებს სტეკს. PDA გამოიყენება ისეთ თეორიებში, რომელიც გვეუბნება რა შეიძლება დაითვალოს კომპიუტერული მანქანების მეშვეობით. ასეთი მანქანას აქვს მეტი შესაძლებლობები ვიდრე სასრულ მდგომარეობიან მანქანას (finite automata), მაგრამ ნაკლები შეუძლია ვიდრე ტურინგის მანქანას. იმის გამო რომ PDA-ში შემომავალი სტრინგი(Input) აღწერილია ფორმალური გრამატიკული ენით, ის შეიძლება გამოვიყენოთ parser-ის დიზაინში. დეტერმინისტულ PDA-ს არ შეუძლია განმარტოს ყველა დეტერმინისტული context-free ენა, მაშინ როდესაც არადეტერმინისტულ PDA-ს შეუძლია განმარტოს ყველა context-free ენა. სტეკის მქონე მანქანას შეუძლია გადაწყვიტოს ენათა უფრო დიდი სიმრავლე ვიდრე დეტერმინისტულ PDA-ს. ასევე, არსებობს ჩადგმულ სტეკიანი მანქანები (A nested stack automaton), რომელიც თავის თავში გულისხმობს უფრო კომპლექსურ მანქანას, კერძოდ ისეთს, რომელსაც სტეკში სასრული სიმბოლოების მაგივრად მნიშნელობებად აქვს ქვესტეკები. ამ სტატიის დარჩენილ ნაწილში აღწერილია არადეტერმინისტული PDA. PDA-ს და სასრულ მდგომარეობიან მანქანას(finite state automata) აქვს ორი განმასხვავებელი ნიშანი: 1. PDA-ს შეუძლია გამოიყენოს სტეკის პირველი ადგილი, რათა გადაწყვიტოს, რომელი გადაადგილება უნდა აიღოს. 2. PDA-ს შეუძლია სტეკით მანიპულირება, გადაადგილების შესასრულებლად. PDA-ს შეუძლია აირჩიოს გადაადგილება შემომავალი სტრინგის ინდექსირებით, არსებული მდგომარეობით და სტეკის თავში მყოფი სიმბოლოთი. ეს ნიშნავს, რომ ეს სამი პარამეტრი სრულად განსაზღვრავს გადაადგილებას, რომელიც არის არჩეული. სასრული მდგომარეობის მქონე მანქანას(finite state automata) უპირველეს ყოვლისა, უყურებს შემომავალ სტრინგს და ახლანდელ მდგომარეობას: მას არ აქვს სტეკი, რათა გამოიყენოს იგი. PDA-ს დამატებული აქვს სტეკი, როგორც პარამეტრი, რომელიც ეხმარება არჩევანის გაკეთებაში. PDA-ს შეუძლია სტეკით მანიპულირება გადაადგილების შესასრულებლად. სასრული ფორმის მანქანა არჩევს ახალ მდგომარეობას მომდევნო გადაადგილების მეშვეობით. მანიპულაციის დროს მანქანას შეუძლია ამოიღოს კონკრეტული სიმბოლო, რომელიც იმყოფება სტეკის თავში. ასევე, ასეთ მანქანას შეუძლია დააიგნოროს და დატოვოს ისე როგორც არის. მანიპულაციის (ისევე როგორც სტეკის იგნორის) არჩევანი განსაზღვრულია გადაადგილების ცხრილით. მოცემული შემომავალი სიგნალით, ახლანდელი მგომარეობითა და სტეკის სიმბოლოთი მანქანას შეუძლია გადავიდეს სხვა მდგომარეობაში და მანიპულაცია მოახდინოს სტეკზე (იღებს ან დებს სიმბოლოს). ზოგადად PDA-ს შეუძლია გააკეთოს სხვადასხვა გამოთვლები და მოქმედებები input-ზე. შედეგი არის დეტერმინისტული PDA და ენა ამ სიტყვების არის დეტერმინისტული context-free ენა. თუმცა ყველა context-free ენა არ არის დეტერმინისტული. ამ ყველაფრიდან გამომდინარეობს ის, რომ DPDA (Deterministic PDA) არის უფრო სუსტი ვარიანტი PDA-ს. ასევე მნიშვნელოვანია ისიც, რომ არ არსებობს ალგორითმი, რომელიც მოცემულ PDA-ს გადაიყვანს ექვივალენტურ DPDA-ში(ცხადია, თუკი ასეთი DPDA არსებობს საერთოდ). თუ ჩვენ დავუშვებთ იმას, რომ სასრულ მანქნას ჰქონდეს ორი სტეკი ერთის ნაცვლად, მივიღებთ გაუმჯობესებულ ვარიანტს, რომელიც ექვივალენტური იქნება ტურინგის მანქანის. როგორც ზემოთ აღვნიშნეთ, არადეტერმინისტულ PDA-ს შეუძლია ერთ მოქმედებაზე მეტის გაკეთება როდესაც რამდენიმე ვარიანტი აქვს. სინამდვილეში ამისთვის საჭიროა, შეიქმნას ახალი მანქანა, რომელიც თავის მხრივ გადაწყვეტს სხვა არჩევანსაც. პრობლემა ის არის, რომ ასეთი მანქანები პრაქტიკაში ხშირად იჭრებიან. ასეთი შემთხვევების იდენტიფიცირება შეიძლება შემდეგნაირად: მანქანის აგების დროს, საჭიროა გამოვცადოთ (გავტესტოთ) ის გრამატიკა, რომელსაც მანქანა იყენებს. ეს შესაძლებლობას გვაძლევს ყველა ასეთ შემთხვევაში გამოვიყენოთ backtracking, რათა გავაუმჯობესოდ წარმადობა. ჩვენ ვიყენებთ სტანდარტულ განსაზღვრებას: რომელიც აღნიშნავს ანბანში შემომავალ სტრინგებს, ხოლო აღნიშნავს ცარიელ სტრინგს. PDA განისაზღვრება 7 ნაწილისგან. ესენია: M = ( Q ,   Σ ,   Γ ,   δ ,   q 0 ,   Z ,   F ) {\displaystyle M=(Q,\ \Sigma ,\ \Gamma ,\ \delta ,\ q_{0},\ Z,\ F)} Q {\displaystyle \,Q} არის სასრული სიმრავლე მდგომარეობებისა (states) Σ {\displaystyle \,\Sigma } არის სასრული სიმრავლე, რომელსაც უწოდებენ შემომავალ ანბანი (input alphabet) Γ {\displaystyle \,\Gamma } არის სასრული სიმრავლე, რომელსაც უწოდებენ სტეკის ანბანს (stack alphabet) δ {\displaystyle \,\delta } არის სასრული ქვესიმრავლე ~ ის, უწოდებენ (transition relation) q 0 ∈ Q {\displaystyle \,q_{0}\in \,Q} არის საწყისი მდგომარეობა (starting state)   Z ∈ Γ {\displaystyle \ Z\in \,\Gamma } სტეკის საწყისი სიმბოლო(initial stack symbol) F ⊆ Q {\displaystyle F\subseteq Q} მდგომარეობა, სადაც იღებს მანქანა სტრინგს (accepting states) ყველა ელემენტი ( p , a , A , q , α ) ∈ δ {\displaystyle (p,a,A,q,\alpha )\in \delta } არის M {\displaystyle M} -ის გადასვლა. მას აქვს განსაზღვრული მნიშვნელობა რომ M {\displaystyle M} მდგომარეობაში p ∈ Q {\displaystyle p\in Q} , a ∈ Σ ∪ { ε } {\displaystyle a\in \Sigma \cup \{\varepsilon \}} input-ით , როგორც ყველაზე მნიშვნელოვანი სტეკის სიმბოლო, შესაძლოა წაიკითხოს a {\displaystyle a} , შეცვალოს მდგომარეობა q {\displaystyle q} -დ, ამოიღოს A {\displaystyle A} , ჩანაცვლებით α ∈ Γ ∗ {\displaystyle \alpha \in \Gamma ^{*}} . ( Σ ∪ { ε } ) {\displaystyle (\Sigma \cup \{\varepsilon \})} გადანაცვლების კომპონენტი გამოიყენება იმის ფორმულირებისთვის, რომ PDA შეუძლია წაიკითხოს შემომავალი სტრინგიდან სიმბოლო, ან დატოვოს input ხელშეუხებელი. ბევრ ტექსტში, გადასვლის დამოკიდებულება არის ჩანაცვლებული შემდეგი ექვივალენტური, ფორმალიზაციით: δ {\displaystyle \,\delta } არის გადასვლის ფუნქცია, შესაბამებით(mapping) Q × ( Σ ∪ { ε } ) × Γ {\displaystyle Q\times (\Sigma \cup \{\varepsilon \})\times \Gamma } სასრული ქვესიმრავლე Q × Γ ∗ {\displaystyle Q\times \Gamma ^{*}} -ისა. δ ( p , a , A ) {\displaystyle \delta (p,a,A)} შეიცავს ყველა შესაძლო ქმედებას p {\displaystyle p} მდგომარეობაში და A {\displaystyle A} სტეკის გამოყენებით, როდესაც კითხულობს a {\displaystyle a} -ს ინფუთად. ერთი წერს ( q , α ) ∈ δ ( p , a , A ) {\displaystyle (q,\alpha )\in \delta (p,a,A)} ზუსტად ფუნქციისთვის, როდესაც ( p , a , A , q , α ) ∈ δ {\displaystyle (p,a,A,q,\alpha )\in \delta } შევნიშნოთ, რომ სასრული ამ შემთხვევაშ არის აუცილებელი. ეს არის ფორმალური განმარტება PDA-ს, რომელიც წყვეტს შემდეგ ენას: { 0 n 1 n ∣ n ≥ 0 } {\displaystyle \{0^{n}1^{n}\mid n\geq 0\}} M = ( Q ,   Σ ,   Γ ,   δ ,   p ,   Z ,   F ) {\displaystyle M=(Q,\ \Sigma ,\ \Gamma ,\ \delta ,\ p,\ Z,\ F)} , სადაც Q = { p , q , r } {\displaystyle Q=\{p,q,r\}} Σ = { 0 , 1 } {\displaystyle \Sigma =\{0,1\}} Γ = { A , Z } {\displaystyle \Gamma =\{A,Z\}} q 0 = p {\displaystyle q_{0}=p} F = { r } {\displaystyle F=\{r\}} δ {\displaystyle \delta } შედგები შემდეგი 6 ინსტრუქციისგან: ( p , 0 , Z , p , A Z ) {\displaystyle (p,0,Z,p,AZ)} , ( p , 0 , A , p , A A ) {\displaystyle (p,0,A,p,AA)} , ( p , ϵ , Z , q , Z ) {\displaystyle (p,\epsilon ,Z,q,Z)} , ( p , ϵ , A , q , A ) {\displaystyle (p,\epsilon ,A,q,A)} , ( q , 1 , A , q , ϵ ) {\displaystyle (q,1,A,q,\epsilon )} , and ( q , ϵ , Z , r , Z ) {\displaystyle (q,\epsilon ,Z,r,Z)} . სიტყვებით რომ ვთქვათ, p {\displaystyle p} მდგომარეობაში ყოველი სიმბოლო 0 {\displaystyle 0} -თვის წავიკითხოთ და ჩავაგდოთ ერთი სიმბოლო A {\displaystyle A} სტეკში. A {\displaystyle A} -ს ჩაგდება სტეკის თავში ზემოდან კიდევ სხვა A {\displaystyle A} -ზე, ფორმულირდება როგორც ამ ორის ჩანაცლება A A {\displaystyle AA} -თი. q {\displaystyle q} მდგომარეობაში ყოველი სიმბოლოსთვის, რომელიც არის 1 {\displaystyle 1} -იანი, წავიკითხოთ და ამოვაგდოთ A {\displaystyle A} სტეკიდან. ნებისმიერ მომენტში მანქანა შიძლება გადაადგილდეს p {\displaystyle p} -დან q {\displaystyle q} მდგომარეობაში. მაშინ როდესაც სტეკი შეიცავს ერთადერთ სიმბოლოს Z {\displaystyle Z} -ს, მანქანას შეუძლია გადასვლა q {\displaystyle q} -დან მიმღებ მდგომარეობაშ r {\displaystyle r} (accepting state). ქვემოთ აღწერილია, როგორ ხდება სხვადასხვა Input-ის გამოთვლა PDA-თი. ა) შემავალი სტრინგი = 0011. გვაქვს გამოთვლის სხვადასხვა ვარიანტი, რომელიც დამოკიდებულია გადასვლაზე p {\displaystyle p} მდგომარეობიდან q {\displaystyle q} მდგომარეობაში. თუმცა, მხოლოდ ერთი იღებს ამ სტრინგს, ანუ არის მიმღები მდგომარეობა (accepting states). (i) ( p , 0011 , Z ) ⊢ ( q , 0011 , Z ) ⊢ ( r , 0011 , Z ) {\displaystyle (p,0011,Z)\vdash (q,0011,Z)\vdash (r,0011,Z)} ფინალური მდგომარეობა იღებს, მაგრამ input ამ შემთხვევაში არ მიიღება, რადგან ის არ კითხულობს. (ii) ( p , 0011 , Z ) ⊢ ( p , 011 , A Z ) ⊢ ( q , 011 , A Z ) {\displaystyle (p,0011,Z)\vdash (p,011,AZ)\vdash (q,011,AZ)} არ არის სხვა შესაძლო ვარიანტი. (iii) ( p , 0011 , Z ) ⊢ ( p , 011 , A Z ) ⊢ ( p , 11 , A A Z ) ⊢ ( q , 11 , A A Z ) {\displaystyle (p,0011,Z)\vdash (p,011,AZ)\vdash (p,11,AAZ)\vdash (q,11,AAZ)} ⊢ ( q , 1 , A Z ) ⊢ ( q , ϵ , Z ) {\displaystyle \vdash (q,1,AZ)\vdash (q,\epsilon ,Z)} ⊢ ( r , ϵ , Z ) {\displaystyle \vdash (r,\epsilon ,Z)} მთავრდება მიმღებ მდგომარეობაში, როდესაც დასრულდება input-ის წაკითხვა. ბ) შემომავალი სტრინგი = 00111. ასევე არის სხვადასხვა ვარიანტი გამოთვლის, თუმცა, არც ერთი არ იღებს შემომავალ სტრინგს (i) ( p , 00111 , Z ) ⊢ ( q , 00111 , Z ) ⊢ ( r , 00111 , Z ) {\displaystyle (p,00111,Z)\vdash (q,00111,Z)\vdash (r,00111,Z)} საბოლოო მდგომარეობა იღებს, მაგრამ input არაა ბოლომდე წაკითხული (ii) ( p , 00111 , Z ) ⊢ ( p , 0111 , A Z ) ⊢ ( q , 0111 , A Z ) {\displaystyle (p,00111,Z)\vdash (p,0111,AZ)\vdash (q,0111,AZ)} არ არის სხვა შესაძლო ვარიანტი (iii) ( p , 00111 , Z ) ⊢ ( p , 0111 , A Z ) ⊢ ( p , 111 , A A Z ) ⊢ ( q , 111 , A A Z ) {\displaystyle (p,00111,Z)\vdash (p,0111,AZ)\vdash (p,111,AAZ)\vdash (q,111,AAZ)} ⊢ ( q , 11 , A Z ) ⊢ ( q , 1 , Z ) {\displaystyle \vdash (q,11,AZ)\vdash (q,1,Z)} ⊢ ( r , 1 , Z ) {\displaystyle \vdash (r,1,Z)} მართალია, საბოლოო მდგომარეობა იღებს input-ს, მაგრამ ეს ის შემთხვევაა, როდესაც არ შეიძლება ვთქვათ, რომ input მიიღო, რადგან შემავალი სტრინგი არ არის ბოლომდე წაკითხული. (GPDA) არის PDA, რომელიც წერს შემომავალი სტრინგის (ცნობილია სიგრძე) სტეკში და ასევე შლის მას სტეკიდან ერთ ბიჯზე. (GPDA) განიმარტება შემდეგნაირად: M = ( Q ,   Σ ,   Γ ,   δ ,   q 0 ,   F ) {\displaystyle M=(Q,\ \Sigma ,\ \Gamma ,\ \delta ,\ q_{0},\ F)} სადაც Q, Σ {\displaystyle \Sigma \,} , Γ {\displaystyle \Gamma \,} , q0 არის განსაზღვრული როგორც PDA. δ {\displaystyle \,\delta } : Q × Σ ϵ × Γ ∗ ⟶ P ( Q × Γ ∗ ) {\displaystyle Q\times \Sigma _{\epsilon }\times \Gamma ^{*}\longrightarrow P(Q\times \Gamma ^{*})} არის ტრანზაციის ფუნქცია. გამოთვლითი წესები GPDA-სთვის არის მსგავსად PDA-სი, განსხვავებით იმისა, რომ ai+1 და bi+1 არიან სტრინგები განსხვავებით სიმბოლოსი. GPDA და PDA არიამ ექვივალენტები, იმიტომ რომ თუ ენა გადაწყვეტადია PDA-თი, მაშინ ასევე ეს ენა გადაწყდება აუცილებლად GPDA-ითაც. დავამტკიცოთ, რომ GPDA და PDA არიან ექვივალენტურები: ვთქვათ, δ {\displaystyle \delta } (q1, w, x1x2...xm) ⟶ {\displaystyle \longrightarrow } (q2, y1y2...yn არის GPDA-ს გადასვლა, სადაც q 1 , q 2 ∈ Q {\displaystyle q_{1},q_{2}\in Q} , w ∈ Σ ϵ {\displaystyle w\in \Sigma _{\epsilon }} , x 1 , x 2 , … , x m ∈ Γ ∗ {\displaystyle x_{1},x_{2},\ldots ,x_{m}\in \Gamma ^{*}} , m ≥ 0 {\displaystyle m\geq 0} , y 1 , y 2 , … , y n ∈ Γ ∗ {\displaystyle y_{1},y_{2},\ldots ,y_{n}\in \Gamma ^{*}} , n ≥ 0 {\displaystyle n\geq 0} . ავაგოთ შესაბამისი PDA: δ ′ {\displaystyle \delta ^{'}} (q1, w, x1) ⟶ {\displaystyle \longrightarrow } (p1, ϵ {\displaystyle \epsilon } ) δ ′ {\displaystyle \delta ^{'}} (p1, ϵ {\displaystyle \epsilon } , x2) ⟶ {\displaystyle \longrightarrow } (p2, ϵ {\displaystyle \epsilon } ) ⋮ {\displaystyle \vdots } δ ′ {\displaystyle \delta ^{'}} (pm-1, ϵ {\displaystyle \epsilon } , xm) ⟶ {\displaystyle \longrightarrow } (pm, ϵ {\displaystyle \epsilon } ) δ ′ {\displaystyle \delta ^{'}} (pm, ϵ {\displaystyle \epsilon } , ϵ {\displaystyle \epsilon } ) ⟶ {\displaystyle \longrightarrow } (pm+1, yn) δ ′ {\displaystyle \delta ^{'}} (pm+1, ϵ {\displaystyle \epsilon } , ϵ {\displaystyle \epsilon } ) ⟶ {\displaystyle \longrightarrow } (pm+2, yn-1) ⋮ {\displaystyle \vdots } δ ′ {\displaystyle \delta ^{'}} (pm+n-1, ϵ {\displaystyle \epsilon } , ϵ {\displaystyle \epsilon } ) ⟶ {\displaystyle \longrightarrow } (q2, y1)