אוטומטים ושפות פורמליות/דקדוקים חסרי הקשר

כעת נרצה לנתח את התכונות של השפות המוכרעות על-ידי אוטומט מחסנית.

על מנת לנתח שפות אלו, נצטרך להגדיר אובייקט חדש הנקרא דקדוק. בהמשך נראה כי הדקדוק אותו נגדיר מתאר בדיוק את כלל השפות המוכרעות על-ידי אוטומט מחסנית.

הגדרה

עריכה

דקדוק חסר הקשר   מוגדר על ידי הרביעיה  , כאשר:

  1.   - קבוצת משתנים
  2.   - קבוצת אותיות סופיות (טרמינלים). קבוצה זו מהווה את האלפבית של השפה הנוצרת.
  3.   - קבוצת כללי יצירה. כל כלל הופך משתנה למחרוזת של אותיות ומשתנים
     
  4.   - סימן ההתחלה. משתנה מתוך  .


אומרים שהדקדוק   יוצר מילה  , אם ניתן להתחיל מהמשתנה  , ועל-ידי ביצוע אחד או יותר מכללי היצירה שב- , להגיע אל המילה  . מסמנים במקרה זה  .

השפה הנוצרת על-ידי הדקדוק  , היא אוסף כל המחרוזות  , אותן ניתן לייצר מ- , על ידי כללי היצירה המוגדרים ב-R. באופן פורמלי,

 

דוגמא

עריכה

הדקדוק חסר ההקשר הבא מייצר את השפה  :

 
 

בדוגמא זו,   כאשר כללי היצירה נתונים לעיל.

למשל, ניצור את המילה 000111:

 

או בצורה מקוצרת  . בשלוש הגזירות הראשונות השתמשנו בכלל היצירה   וברביעית בכלל  .



עץ יצירה

עריכה

ניתן להציג את יצירת המילה בתור עץ-יצירה. למשל, נתון הדקדוק המתואר על ידי שני כללי היצירה:  . דקדוק זה מאפשר ניתן לייצר את המילה aaa באופן הבא,

 

ניתן לתאר את שרשרת הגזירות על-ידי עץ-יצירה:

 

בצורה זו המילה המתקבלת הינה עלי העץ, הנקראים משמאל לימין (סדר העלים בסריקת עומק-תחילה, DFS).

הקשר בין שפות חסרות הקשר לאוטומט מחסנית

עריכה

בחלק זה נראה כי אוטומט מחסנית שקול לדקדוק חסר הקשר.

יצירת אוטומט מדקדוק חסר הקשר

עריכה

כיוון זה קל - ומזכיר מאד, מבחינת הרעיונות, ביצוע סריקת DFS בעץ - על ידי מחסנית.

נניח כי נתון דקדוק  . נבנה ממנו אוטומט המבצע את האלגוריתם להלן:

 

מתיאור זה ניתן להבין מדוע דקדוק חסר הקשר הוא הכלי המתאים לתיאור שפות המתקבלות על-ידי אוטומט. מכיוון שהזיכרון של האוטומט הוא מחסנית, האוטומט מוגבל לפעולות מחסנית, ולאלגוריתמים שניתנים למימוש קל על-ידי מחסנית (למשל DFS). דקדוק חסר הקשר ממפה כל מילה בשפה ל"עץ יצירה" המתאים למילה, כאשר המילה היא למעשה עלי העץ לפי הסדר המתקבל בסריקת DFS.

  1. האוטומט מתחיל על-ידי הכנסה של הסימן ההתחלתי S למחסנית.
  2. בכל צעד מוציאים את הסימן שבראש המחסנית:
    1. אם הסימן שנשלף הינו משתנה, בוחרים באופן לא-דטרמיניסטי את אחד מחוקי היצירה המתאימים לאותו המשתנה, ומכניסים את הסימנים המתאימים למחסנית (כלומר, אם שלפנו את המשתנה A, ובחרנו בכלל היצירה  , נכניס למחסנית   (בסדר הפוך, כדי שה-a יהיה בראש המחסנית)).
    2. אם הסימן הינו טרמינל - משווים את האות לאות הקלט הנוכחית (כלומר, קיים מעבר לכל אות קלט עם האות המקבילה בראש המחסנית).

אפשר להבין מהאלגוריתם לעיל, שהאוטומט למעשה מבצע את סדרת כללי היצירה המתאימים על המחסנית, על-ידי בחירתם באופן לא דטרמיניסטי. אם מילת הקלט מיוצרת על-ידי הדקדוק, אזי קיים רצף בחירות לא-דטרמיניסטיות שבו ייבחרו בדיוק אותם כללים שמייצרים את מילת הקלט, והמכונה תקבל את הקלט.


יצירת דקדוק מאוטומט סופי

עריכה

בחלק זה נראה שבהנתן אוטומט מחסנית, ניתן ליצור ממנו דקדוק חסר הקשר, המתאר את השפה המוכרעת על-ידי האוטומט. הרעיון בבניית הדקדוק הוא לדמות את מהלך הריצה של האוטומט בשלבים השונים של הריצה.

נניח כי נתון לנו אוטומט מחסנית  , ונניח כי תמיד בעת קבלת המילה, המחסנית של האוטומט ריקה (קל להפוך כל אוטומט-מחסנית לאוטמט המרוקן את המחסנית לפני הקבלה.) כמו כן נניח כי קיים רק מצב מקבל יחיד   (גם דרישה זו קלה להשגה, למשל על-ידי מעבר אפסילון מכל המצבים המקבלים למצב מקבל יחיד, והפיכת המצבים המקבלים המקוריים למצבים רגילים).
מהאוטומט הנתון נבנה דקדוק  . נתאר כעת את המרכיבים השונים של הדקדוק:

  • טרמינלים - מהווים את האלפבית של השפה.
  • משתנים - כל המשתנים יהיהו מהצורה  כאשר   הינם מצבים כלשהם של האוטמט. נרצה שהמשתנה   ייצר את כל המחרוזות שמקבל אוטומט המתחיל במצב   (עם מחסנית ריקה) ומסיים במצב   (שוב, עם מחסנית ריקה, לפי ההנחות שאנחנו עובדים). במילים אחרות,   מתאר את פעולת האוטומט ממצב   ועד למצב   בהנחה שהאוטומט לא קורא את תוכן המחסנית מעבר לנקודה שהיא נמצאת כרגע, אבל אולי משתמש בה (ואז מרוקן אותה חזרה למצב ההתחלתי).
  • מצב התחלתי - מתיאור המשתנים לעיל, ברור כי השפה של האוטמט מיוצרת על-ידי  , המתאר את כל המחרוזות שהאוטומט מקבל אם התחיל במצב   עם מחסנית ריקה, וסיים במצב המקבל (היחידי) עם מחסנית ריקה. לכן משתנה זה יהיה המשתנה ההתחלתי שלנו:  
  • כללי יצירה - כעת נגדיר את כללי היצירה של הדקדוק לפי התנהגות המכונה. נפריד לשלושה מקרים שונים:
    1. האוטומט התחיל במצב   וסיים במצב  , אבל במהלך הדרך, הגיע למצב   כאשר המחסנית היתה ריקה. עבור מקרים מסוג זה נוסיף את כלל היצירה  , שמשמעותו שכל המחרוזות שהאוטומט "מקבל" אם התחיל במצב   וסיים במצב  , בלי לקרוא את התוכן הקיים על המחסנית עצמה, הוא למעשה כל המחרוזות שהאוטמט "מקבל" בין   ל- , משורשרות לכל המחרוזות שהאוטמט "מקבל" כשמתחיל ב-  ומסיים ב- . לכן, לכל שלשת מצבים   נוסיף את כלל היצירה  
    2. המקרה השני הוא שהאוטמט, במהלך הדרך בין   ל-  לעולם לא מגיע למצב בו המחסנית ריקה (בהנחה שהתחיל עם מחסנית ריקה). במקרה זה, בצעד הראשון האוטמט קורא מהקלט את הסימן x, מכניס למחסנית אות כלשהי a, ועובר למצב  . בצעד האחרון נניח שהאוטומט במצב   כאשר הוא קורא מהקלט את האות y, עובר למצב   ובהכרח מוציא מהמחסנית את האות a - לא ייתכן שנשלפה אות אחרת כי אף פעם במהלך הדרך המחסנית לא רוקנה, ולכן הסימן שהוכנס בצעד הראשון עדיין שם. כלל היצירה המתאים למקרה זה הוא מהצורה  . חשוב לציין שכלל יצירה כנ"ל קיים רק אם המכונה יכולה לעבור מ-  ל- , ומ-  ל-  על ידי קריאת x,y מהקלט (בהתאמה), ועל-ידי הכנסה למחסנית ושליפה של אותה האות a. במילים אחרות, נוסיף את כללי היצירה הבאים
       
      אם מתקיימים התנאים
       
    3. התנאי השלישי הוא מקרה הקצה   בו שני המצבים זהים. משתנה זה למעשה מייצר את המחרוזות המתקבלות על-ידי האוטומט אם התחיל וסיים באותו מצב, מבלי לקרוא את התוכן הקיים על המחסנית. נוסף על המקרים המתוארים במקרה (2) לעיל, צריך לזכור שייתכן כי המצב של האוטומט לא השתנה בכלל, המתאים למקרה בו לא נקראה אף אות קלט. בשל כך נוסיף את כלל היצירה
       
      עבור כל מצב  . קל לראות שאלמלא כלל-יצירה זה, כמות המשתנים רק גדלה ולעולם לא נסיים עם מחרוזת שכולה טרמינלים.

הכללים לעיל מכסים את כלל האפשרויות של פעולת האוטומט, למעט המקרה בו האוטומט לא כותב דבר למחסנית (מעבר מהצורה  ) או קורא וכותב בו-זמנית  . אבל ניתן להמיר כל אוטומט מחסנית כך שמעברים מהסוג הנ"ל לא יופיעו בו (למשל, על-ידי הוספת מצבי ביניים שכותבים למחסנית ואז מוציאים, וכד').


הפרק הקודם:
אוטומט מחסנית
דקדוקים חסרי הקשר הפרק הבא:
תכונות של שפות חסרות הקשר