יחידה 2.1 חיפוש מיודע, אי-שוויון המשולש ועקביות

תנאי אופטימליות בחיפוש מיודע ($A^*$) ועקביות היוריסטית

💡 מבוא פדגוגי: הקסם של $A^*$ והמלכודת הנסתרת

שלום חברים! בפרק הקודם פגשנו את אלגוריתם $A^*$ והתפעלנו מפונקציית ההערכה ההרמונית שלו: $f(n) = g(n) + h(n)$. הרעיון הוא פשוט וגאוני: לקחת את עלות העבר המוכחת $g(n)$ ולחבר אליה הערכה של שארית הדרך $h(n)$. אך כאן נשאלת שאלת מיליון הדולר: באילו תנאים מתמטיים מובטח ש-$A^*$ יחזיר תמיד את הפתרון האופטימלי הזול ביותר? כפי שנראה מיד, הדרישה משתנה באופן דרמטי בין חיפוש עץ (Tree Search) הדורש רק קבילות, לבין חיפוש גרף (Graph Search) המחייב תכונה מחמירה בהרבה: עקביות (מונוטוניות). בואו נצלול פנימה ונפרק את המתמטיקה שלב אחר שלב.

🎯 1. היוריסטיקה קבילה (Admissible Heuristic) - התנאי לחיפוש עץ

הגדרה פורמלית: היוריסטיקה $h(n)$ נקראת קבילה אם לכל צומת $n$ במרחב המצבים, היא לעולם אינה מעריכה הערכת יתר (Never Overestimates) את עלות ההגעה האמיתית המינימלית למטרה.

$$\forall n: \quad 0 \le h(n) \le h^*(n), \qquad \text{and} \quad \forall G \in \text{Goals}: \quad h(G) = 0$$

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

מדוע קבילות מספיקה לאופטימליות ב-Tree Search?

נניח בשלילה ש-$A^*$ בחר לסיים עם יעד סאב-אופטימלי $G_2$ שעלותו $g(G_2) > C^*$. מאחר ש-$G_2$ הוא מטרה, מתקיים $f(G_2) = g(G_2) > C^*$.
אולם, לאורך המסלול אל היעד האופטימלי קיים צומת $n$ שטרם הורחב ונמצא בחזית (Frontier). מאחר ש-$h$ קבילה: $$f(n) = g(n) + h(n) \le g(n) + h^*(n) = C^*$$ לפיכך מתקיים תמיד $f(n) \le C^* < f(G_2)$. תור הקדימויות יעדיף בהכרח להרחיב את $n$ לפני שליפת $G_2$, ולכן $G_2$ לעולם לא יישלף לפני מציאת הפתרון האופטימלי!

📐 2. היוריסטיקה עקבית / מונוטונית (Consistent / Monotonic Heuristic) - התנאי לחיפוש גרף

הגדרה פורמלית: היוריסטיקה $h(n)$ נקראת עקבית (Consistent) אם לכל צומת $n$ ולכל עוקב $n'$ של $n$ שנוצר על ידי פעולה $a$ בעלות $c(n, a, n')$, מתקיים אי-שוויון המשולש (Triangle Inequality):

$$h(n) \le c(n, a, n') + h(n') \iff h(n) - h(n') \le c(n, a, n')$$

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

ההשלכה המתמטית הישירה: מונוטוניות עולה של ערכי $f(n)$

נחשב את ערך ה-$f$ של הצומת העוקב $n'$: $$f(n') = g(n') + h(n') = g(n) + c(n, a, n') + h(n') \ge g(n) + h(n) = f(n)$$ ערכי ה-$f(n)$ לאורך כל נתיב חיפוש הם מונוטוניים עולים (אי-יורדים). המשמעות המעשית הקריטית: כאשר צומת נשלף מה-Frontier, מובטח שנמצא המסלול האופטימלי הזול ביותר אליו. לכן ניתן להכניסו ל-Explored Set (רשימה סגורה) ולעולם לא לפתוח אותו מחדש!

משפט חשוב: יחסי ההכלה בין קבילות לעקביות • כל היוריסטיקה עקבית היא בהכרח קבילה: $Consistent \implies Admissible$.
• ההפך אינו נכון: קיימות היוריסטיקות קבילות לחלוטין שאינן עקביות! בחיפוש גרף, חוסר עקביות מוביל לאסון אלגוריתמי.

⚠️ 3. הדוגמה הנגדית הקלאסית: כשל $A^*$ בחיפוש גרף עם היוריסטיקה קבילה שאינה עקבית

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

שרטוט טופולוגי: גרף הדוגמה הנגדית Counterexample Graph
S
h(S) = 0
צומת התחלה
A
h(A) = 10
קשת מ-S בעלות 1
B
h(B) = 0
קשת מ-S בעלות 1
C
h(C) = 5
קשת מ-A (עלות 1)
קשת מ-B (עלות 2)
G
h(G) = 0
קשת מ-C בעלות 10
(צומת מטרה)
• מסלול עליון: $S \to A \to C \to G$ בעלות כוללת: $1 + 1 + 10 = \mathbf{12}$ (המסלול האופטימלי האמיתי!).
• מסלול תחתון: $S \to B \to C \to G$ בעלות כוללת: $1 + 2 + 10 = \mathbf{13}$ (מסלול סאב-אופטימלי נחות!).
✓ הוכחת קבילות ההיוריסטיקה (Admissibility)
  • $h^*(C) = 10 \ge h(C) = 5$ (קביל).
  • $h^*(B) = c(B,C) + c(C,G) = 2 + 10 = 12 \ge h(B) = 0$ (קביל).
  • $h^*(A) = c(A,C) + c(C,G) = 1 + 10 = 11 \ge h(A) = 10$ (קביל).
  • $h^*(S) = 1 + 1 + 10 = 12 \ge h(S) = 0$ (קביל).

מסקנה: אין שום הערכת יתר באף צומת, ולכן h קבילה לחלוטין!

✗ הוכחת חוסר עקביות (Inconsistency)

נתבונן בקשת $A \to C$ שעלותה $c(A,C) = 1$: $$h(A) - h(C) = 10 - 5 = 5$$ אך אי-שוויון המשולש דורש $h(A) \le c(A,C) + h(C) = 1 + 5 = 6$.
מכיוון ש-$h(A) = 10 > 6$, אי-השוויון אינו מתקיים!

מסקנה: ההיוריסטיקה אינה עקבית (מונוטוניות נשברת)!

💥 מהלך הרצת החיפוש בגרף (Graph Search) צעד-אחר-צעד:

  1. הרחבת $S$: נוצרים $B$ עם $f(B) = g(B) + h(B) = 1 + 0 = \mathbf{1}$, ו-$A$ עם $f(A) = 1 + 10 = \mathbf{11}$. החזית: $\{B(f=1), A(f=11)\}$.
  2. הרחבת $B$: $B$ נשלף (הקטן ביותר). יורשו הוא $C$ במסלול התחתון: $g(C) = 1 + 2 = 3$, $f(C) = 3 + 5 = \mathbf{8}$. החזית כעת: $\{C(f=8), A(f=11)\}$.
  3. הרחבת $C$ (המלכודת!): $C$ נשלף (כי $8 < 11$) ומוכנס ל-Explored Set! יורשו הוא המטרה $G$ עם $g(G) = 3 + 10 = 13$, $f(G) = 13$. החזית כעת: $\{A(f=11), G(f=13)\}$.
  4. הרחבת $A$ (האסון): $A$ נשלף ($f=11$). יורשו הוא הצומת $C$ במסלול העליון הזול: $g(C) = 1 + 1 = \mathbf{2}$. אבל בחיפוש גרף רגיל, מאחר ש-$C$ כבר נמצא ב-Explored Set, האלגוריתם מתעלם ממנו ומסרב לפתוח אותו מחדש! הנתיב הזול נזרק לפח!
  5. עצירה וסיום: הצומת הבא שנשלף מהחזית הוא $G$. האלגוריתם מחזיר את המסלול הנחות $S \to B \to C \to G$ בעלות 13 במקום 12!

⚙️ 4. אלגוריתם $A^*$ הפורמלי בגרף: פסאודוקוד ומנגנון הפתיחה מחדש (Re-opening)

בספרות האקדמית של בינה מלאכותית, אלגוריתם $A^*$ בגרף מוגדר בקפדנות באמצעות שתי קבוצות צמתים מרכזיות: $\text{OPEN}$ (תור קדימויות של צמתים שנמצאו וטרם הורחבו, ממוין לפי $f(n)$ עולה) ו-$\text{CLOSE}$ (קבוצת הצמתים שכבר נשלפו והורחבו בעבר).

פסאודוקוד פורמלי: אלגוריתם ASTAR(s₀)
function ASTAR(s_0):
    // s_0 is the initial state
    OPEN = PriorityQueue() sorted by f(n) ascending
    CLOSE = Set()
    
    // Initialize root node
    g(s_0) = 0
    f(s_0) = g(s_0) + h(s_0)
    parent(s_0) = null
    OPEN.insert(s_0)
    
    while not OPEN.isEmpty():
        n = OPEN.extractMin()  // node with lowest f(n)
        
        if isGoal(n):
            return constructPath(n)  // SUCCESS: return optimal path
            
        CLOSE.add(n)
        
        for each successor n' of n generated by action a with cost c(n, a, n'):
            new_g = g(n) + c(n, a, n')
            
            if n' in OPEN:
                if new_g < g(n'):
                    // Found a cheaper path to an unexpanded frontier node!
                    g(n') = new_g
                    f(n') = g(n') + h(n')
                    parent(n') = n
                    OPEN.decreaseKey(n')
                    
            else if n' in CLOSE:
                if new_g < g(n'):
                    // CRITICAL EDGE-CASE: Found cheaper path to an already-closed node!
                    // This can ONLY happen if h is NOT consistent!
                    g(n') = new_g
                    f(n') = g(n') + h(n')
                    parent(n') = n
                    CLOSE.remove(n')
                    OPEN.insert(n')  // RE-OPENING node from CLOSE to OPEN!
                    
            else:
                // Brand new undiscovered state
                g(n') = new_g
                f(n') = g(n') + h(n')
                parent(n') = n
                OPEN.insert(n')
                
    return FAILURE  // No path exists to goal
התובנה של מנגנון הפתיחה מחדש (Re-opening):

הבחינו בבלוק else if n' in CLOSE: אם ההיוריסטיקה אינה עקבית (כמו בדוגמה הנגדית עם צומת $C$), ייתכן שנגלה מאוחר יותר מסלול זול יותר לצומת שכבר הורחב ונסגר! כדי ש-$A^*$ יישאר אופטימלי במקרה כזה, הוא חייב לשלוף את $n'$ מתוך CLOSE ולהחזירו ל-OPEN. אולם, פתיחה מחדש זו עלולה לגרום לאותו צומת להיפתח ולהיסגר שוב ושוב מספר אקספוננציאלי של פעמים במקרה הגרוע!

📜 5. הוכחה מתמטית פורמלית: למה 1 ומשפט הקבילות (Admissibility Theorem)

ההוכחה המלאה לכך שקבילות גוררת אופטימליות מבוססת על למה מתמטית מרכזית:

למה 1 (קיום צומת פתוח על מסלול אופטימלי) Fundamental Lemma

ניסוח הלמה: אם $h$ היוריסטיקה קבילה, אזי בכל צעד של אלגוריתם $A^*$ לפני עצירתו, קיים בתור $\text{OPEN}$ לפחות צומת אחד $n$ הנמצא על מסלול אופטימלי כלשהו מ-$s_0$ אל צומת מטרה אופטימלי $G^*$, כך שערך ה-$f$ שלו חסום על ידי העלות האופטימלית:

$$f(n) \le C^*$$
מהלך הוכחת למה 1:
  1. יהי $P = (s_0 = v_0, v_1, v_2, \dots, v_k = G^*)$ מסלול אופטימלי מפתח מצב ההתחלה אל מטרה $G^*$, שעלותו הכוללת היא $C^*$.
  2. בתחילת הריצה $s_0 \in \text{OPEN}$, ולכן עבור $n = s_0$: $$f(s_0) = g(s_0) + h(s_0) = 0 + h(s_0) \le h^*(s_0) = C^*$$ (נובע ישירות מקבילות $h$).
  3. בכל צעד שבו $A^*$ שולף צומת מ-$\text{OPEN}$ ומכניסו ל-$\text{CLOSE}$, אם הצומת הוא על המסלול $P$, לפחות עוקב אחד שלו על המסלול $P$ מוכנס ל-$\text{OPEN}$ (או שכבר נמצא בו).
  4. לפיכך, כל עוד היעד האופטימלי טרם נשלף, תמיד קיים צומת $n \in P$ הנמצא ב-$\text{OPEN}$, כך שכל אבותיו על המסלול $P$ כבר הורחבו ונמצאים ב-$\text{CLOSE}$.
  5. מאחר ש-$n$ הגיע דרך המסלול האופטימלי $P$, העלות שנצברה אליו היא אופטימלית במדויק: $g(n) = g^*(n)$.
  6. מהגדרת הקבילות של $h$, מתקיים $h(n) \le h^*(n)$. נחבר את שני האגפים: $$f(n) = g(n) + h(n) = g^*(n) + h(n) \le g^*(n) + h^*(n) = C^*$$ מש"ל למה 1!
משפט האופטימליות המרכזי של $A^*$ (Admissibility Theorem):

הוכחה בשלילה: נניח בשלילה ש-$A^*$ עצר והחזיר צומת מטרה סאב-אופטימלי $G_2$ שעלותו $g(G_2) > C^*$.
ברגע שליפת $G_2$ מתוך $\text{OPEN}$, מכיוון שהוא צומת מטרה מתקיים $h(G_2) = 0$, ולכן: $$f(G_2) = g(G_2) + h(G_2) = g(G_2) > C^*$$ אולם לפי למה 1, באותו רגע ממש היה קיים ב-$\text{OPEN}$ צומת $n$ הנמצא על המסלול האופטימלי כך ש-$f(n) \le C^*$.
מכאן נובעת שרשרת אי-השוויונים: $$f(n) \le C^* < f(G_2)$$ היות ש-$\text{OPEN}$ הוא תור קדימויות השולף תמיד את הצומת בעל ערך $f$ המינימלי, האלגוריתם היה חייב לשלוף את $n$ לפני שישלוף אי-פעם את $G_2$! סתירה להנחה ש-$G_2$ נשלף. לפיכך, $A^*$ לעולם לא ישלוף מטרה סאב-אופטימלית. $A^*$ מחזיר תמיד פתרון אופטימלי!

💎 6. משפט העקביות / מונוטוניות: מדוע לעולם לא פותחים מחדש מ-CLOSE?

כאשר ההיוריסטיקה $h(n)$ מקיימת את אי-שוויון המשולש ($h(n) \le c(n, a, n') + h(n')$), מתרחשת תופעה אלגוריתמית בעלת חשיבות עליונה:

1. מונוטוניות אי-יורדת של ערכי $f$

לכל צומת $n$ ועוקב $n'$: $$f(n') = g(n') + h(n') = g(n) + c(n, a, n') + h(n')$$ מאי-שוויון המשולש נובע $c(n, a, n') + h(n') \ge h(n)$, ולכן: $$f(n') \ge g(n) + h(n) = f(n)$$ ערכי $f$ לאורך כל ענף הם מונוטוניים אי-יורדים!

2. סגירה סופית של צמתים ב-CLOSE

מסקנה ישירה: צמתים נשלפים מ-$\text{OPEN}$ בסדר שאינו יורד של ערכי $f$. ברגע שצומת $n$ נשלף מ-$\text{OPEN}$ ונכנס ל-$\text{CLOSE}$, מובטח שנמצא המסלול הקצר והזול ביותר אליו ($g(n) = g^*(n)$)! אין שום צורך לפתוח מחדש צמתים מ-CLOSE, וכל צומת מורחב בדיוק פעם אחת!

👑 7. משפט השליטה (Dominance) ושילוב היוריסטיקות ($\max$)

כיצד נשווה בין שתי היוריסטיקות קבילות שונות, ואיך נוכל להפיק את המרב ממספר היוריסטיקות זמינות? ניתוח הדומיננטיות המדויק:

משפט השליטה (Dominance Theorem):

אם $h_1(n)$ ו-$h_2(n)$ שתיהן היוריסטיקות קבילות, ולכל צומת $n$ מתקיים: $$h_2(n) \ge h_1(n)$$ אזי נאמר ש-$h_2$ שולטת ב-$h_1$ ($h_2$ dominates $h_1$).

מסקנה: $A^*$ שיופעל עם $h_2$ יפתח קבוצת צמתים המוכלת בקבוצת הצמתים שיפתח $A^*$ עם $h_1$. כלומר, $h_2$ לעולם לא תפתח יותר צמתים מ-$h_1$ – היא יעילה יותר חישובית!
שילוב היוריסטיקות באמצעות פונקציית המקסימום:

אם יש לנו $k$ היוריסטיקות קבילות שונות $h_1, h_2, \dots, h_k$ (שאף אחת מהן אינה שולטת באחרת בכל המרחב), נגדיר היוריסטיקה חדשה: $$\hat{h}(n) = \max\{h_1(n), h_2(n), \dots, h_k(n)\}$$

✓ $\hat{h}$ היא קבילה (מאחר שכל $h_i(n) \le h^*(n)$).
✓ $\hat{h}$ היא עקבית (אם כל $h_i$ עקביות).
✓ $\hat{h}$ שולטת בכל אחת מהן בנפרד!

📊 8. השוואת תכונות וסיבוכיות של אלגוריתמי חיפוש (עיוור ומיודע)

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

אלגוריתם שלמות (Completeness) אופטימליות (Optimality) סיבוכיות זמן סיבוכיות מקום (זיכרון)
DFS (עומק) לא (אם יש מעגלים/אינסוף) לא מובטחת O(bᵐ) O(bm) - לינארי!
BFS (רוחב) כן (אם b סופי) כן (אם עלות קשתות אחידה) O(bᵈ) O(bᵈ) - פיצוץ RAM!
IDS (מעמיק איטרטיבי) כן כן (כמו BFS) O(bᵈ) O(bd) - לינארי!
UCS (עלות אחידה) כן (אם c(e) ≥ ε > 0) כן (תמיד אופטימלי!) O(b¹⁺⌊C*/ε⌋) O(b¹⁺⌊C*/ε⌋) - מעריכי
A* (חיפוש עץ) כן מותנה בקבילות (Admissible) תלוי באיכות היוריסטיקה מעריכי (שומר חזית)
A* (חיפוש גרף) כן מותנה בעקביות (Consistent) O(bᵈ) במקרה הגרוע מעריכי (חזית + Explored)
1. מה קורה כש-h(n) = 0?

פונקציית ההערכה מתנוונת ל-$f(n) = g(n) + 0 = g(n)$. האלגוריתם הופך במדויק ל-חיפוש בעלות אחידה (UCS)!

2. סביבות רציפות (רובוטיקה):

מרחבים רציפים עוברים דיסקרטיזציה שיטתית (חלוקה לתאים, מפות דרכים הסתברותיות PRM או גרפי נראות), ואז $A^*$ מוחל עליהם באופטימליות מלאה.

3. מעגלים בעלות אפס:

BFS שומר על שלמות (תלוי רק בעומק), אך UCS עלול להיתקע בלולאה אינסופית אם לא מתקיים התנאי $c(e) \ge \epsilon > 0$.

4. מרחק מנהטן לצריח בשחמט:

אינו קביל! צריח גומא 10 משבצות בצעד יחיד בעלות 1, בעוד שמרחק מנהטן יעריך 10 (הערכת יתר חמורה הפוסלת אופטימליות).

5. גרף שרשרת לינארית (1,000 צמתים עוקבים):

אלגוריתם IDS מבצע $1+2+...+n$ פיתוחים ומפגין סיבוכיות ריבועית $O(n^2)$, לעומת DFS שמגיע ליעד בזמן לינארי מהיר $O(n)$.

🧪

התנסות מעשית: מעבדת אי-שוויון המשולש וכשל עקביות ב-$A^*$

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

איך משתמשים בסימולטור?
• מעבר בין מצבי חיפוש: בחרו בראש המעבדה בין "חיפוש גרף" (הנועל צמתים ב-Closed Set) לבין "חיפוש עץ" (המאפשר פתיחה מחדש).
• סליידר היוריסטיקה: שנו את ערך $h(A)$ מ-10 לערכים קטנים מ-6, וראו כיצד אי-שוויון המשולש מתקיים מחדש והתוצאה האופטימלית חוזרת.
• צעד אחר צעד / הרצה אוטומטית: לחצו על "צעד הבא" או "Auto Run" כדי לצפות בהסברים הפדגוגיים המפורטים של כל שלב.
יחידה 2.2 עץ המספרים האינסופי, חיפוש דו-כיווני ורפורמולציה

טופולוגיית מרחב מצבים והמרות ייצוג (Reformulation)

💡 כוחו של ייצוג הבעיה (Data Representation)

ברוכים הבאים לאחת התובנות המרתקות והעמוקות ביותר בכל מדעי המחשב והבינה המלאכותית! בפרק הקודם למדנו כיצד להריץ אלגוריתמי חיפוש עיוורים ומיודעים: בונים תור, מרחיבים צמתים, מחזיקים רשימת סגורים, ונלחמים בפיצוץ האקספוננציאלי. אך כאן נשאלת שאלה פילוסופית עמוקה: האם אנו באמת חייבים "לחפש"? נלמד דרך שאלת המופת של ראסל ונורוויג (שאלה 3.15) כיצד הבנה טופולוגית של מרחב הבעיה מאפשרת לבצע חיפוש דו-כיווני עם מקדם הסתעפות פלאי של $b=1$, ואיך רפורמולציה (ניסוח מחדש) בבסיס בינארי מעלימה לחלוטין את החיפוש ומספקת פתרון ישיר ב-$O(1)$!

🌳 1. הגדרת הבעיה: מרחב המספרים השלמים (Russell & Norvig 3.15)

נתונה בעיית חיפוש מתמטית פשוטה לכאורה:

מפרט מרחב המצבים:
• מצב התחלה (Initial State): $S_0 = 1$ (המספר 1 כשורש העץ).
• אופרטורים חוקיים (Successor Function): מכל מצב $k \in \mathbb{N}$ קיימות בדיוק שתי פעולות:
1. ענף שמאל: מעבר למצב $2k$ (הכפלה ב-2)
2. ענף ימין: מעבר למצב $2k + 1$ (הכפלה ב-2 והוספת 1)
• מצב מטרה (Goal State): להגיע למספר מסוים (למשל, $G = 11$).
• עלות צעד: עלות אחידה של $1$ לכל מעבר קשת.
תכונות טופולוגיות מכריעות של המרחב:
1. עץ בינארי שלם ואינסופי: כל מספר טבעי $n \in \mathbb{N}$ מופיע בעץ בדיוק פעם אחת!
2. א-ציקליות מוחלטת (Acyclic): אין שום מעגלים במרחב (המספרים תמיד גדלים בצעד קדימה).
3. אין צורך ברשימת מצבים סגורים (Explored / Closed List): מאחר שאין מסלולים כפולים לאותו מצב, חיפוש עץ (Tree Search) פועל כאן ללא סכנת לולאות אינסופיות, מה שחוסך זיכרון רב של טבלאות גיבוב!

📋 2. ניתוח מעקב יבש (Dry Trace) של אלגוריתמי החיפוש עבור יעד $G = 11$

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

א. חיפוש לרוחב (Breadth-First Search - BFS) FIFO Queue

BFS סורק את העץ שכבה אחר שכבה (רמות עומק מהשורש), משמאל לימין:

  • • רמה 0 (עומק 0): [1]
  • • רמה 1 (עומק 1): [2, 3]
  • • רמה 2 (עומק 2): [4, 5, 6, 7]
  • • רמה 3 (עומק 3): [8, 9, 10, 11] ← עצירה מידית במטרה!
סדר הביקור המלא ב-BFS: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
ב. חיפוש מוגבל עומק (Depth-Limited Search - DLS) עם מגבלה $\text{limit} = 3$ LIFO Stack (Limit = 3)

DLS צולל לעומק הענף השמאלי עד למגבלת העומק 3, ואז מבצע נסיגה (Backtrack):

  1. ירידה שמאלה: $1 \to 2 \to 4 \to 8$ (הגענו לעומק 3, נסוגים חזרה ל-4).
  2. פנייה ליורש הימני של 4: הצומת 9 (עומק 3, נסוגים חזרה ל-2).
  3. פנייה ליורש הימני של 2: הצומת 5 (עומק 2).
  4. ירידה שמאלה מ-5: הצומת 10 (עומק 3, נסוגים חזרה ל-5).
  5. פנייה ליורש הימני של 5: הצומת 11 ← הגענו למטרה!
סדר הביקור המלא ב-DLS: 1, 2, 4, 8, 9, 5, 10, 11
ג. חיפוש מעמיק איטרטיבי (Iterative Deepening Search - IDS) Iterative DLS

IDS מריץ סדרת חיפושי DLS מוגבלי עומק הולכים וגדלים מ-$l = 0$ ועד למציאת המטרה:

  • • איטרציה $l=0$: 1
  • • איטרציה $l=1$: 1, 2, 3
  • • איטרציה $l=2$: 1, 2, 4, 5, 3, 6, 7
  • • איטרציה $l=3$: 1, 2, 4, 8, 9, 5, 10, 11 (עצירה במטרה!)
סדר כלל הצמתים שנוצרו לאורך כל הריצה: 1, 1, 2, 3, 1, 2, 4, 5, 3, 6, 7, 1, 2, 4, 8, 9, 5, 10, 11

↔️ 3. החיפוש הדו-כיווני (Bidirectional Search): עקרון הפעולה הכללי ומקדם ההסתעפות $b=1$ לאחור

בפרק הקודם פגשנו את אלגוריתמי החיפוש החד-כיווניים (הסורקים מההתחלה ליעד). חיפוש דו-כיווני (Bidirectional Search) מציע תפיסה מהפכנית: להריץ שני חיפושים מקבילים בו-זמנית – אחד קדימה ממצב ההתחלה $s_0$, והשני אחורה מצב/י המטרה $G$, עד שהחזיתות שלהם נפגשות באמצע!

המסגרת הפורמלית של חיפוש דו-כיווני כללי:
1. תנאי מוקדם: אופרטורים הפיכים ($Succ^{-1}$)

כדי לחפש אחורה מהמטרה, חייבת להתקיים פונקציית קודמים יעילה $Succ^{-1}(s)$: $$\forall a: s \xrightarrow{a} s' \iff s \in Succ^{-1}(s')$$ אם הפעולות אינן הפיכות בקלות, חיפוש לאחור הופך לבלתי אפשרי.

2. תנאי העצירה והמפגש (Intersection)

האלגוריתם בודק בכל צעד האם הצומת שנשלף בחזית האחת כבר קיים בחזית או בקבוצת הסגורים של הכיוון הנגדי: $$\text{Frontier}_F \cap \text{Frontier}_B \neq \emptyset \quad \lor \quad n \in \text{Explored}_{\text{Opposite}}$$

החיסכון האקספוננציאלי בסיבוכיות:

במקום חיפוש עמוק אחד בעומק $d$ בעל סיבוכיות $O(b^d)$, אנו מחפשים בשני חצאי עצים עד לעומק $d/2$: $$\text{Time \& Space} = O(b^{d/2} + b^{d/2}) = O(2 \cdot b^{d/2}) \ll O(b^d)$$ דוגמה מספרית: עבור מקדם הסתעפות $b = 10$ ועומק מטרה $d = 8$:
• חיפוש חד-כיווני מייצר: $10^8 = \mathbf{100,000,000}$ צמתים.
• חיפוש דו-כיווני מייצר: $2 \times 10^{8/2} = 2 \times 10^4 = \mathbf{20,000}$ צמתים בלבד!
קיצוץ של פי 5,000 במספר הצמתים ובזיכרון ה-RAM!

מקרה המבחן המיוחד: עץ המספרים האינסופי (Russell & Norvig 3.15)

בבעיית המספרים השלמים שלנו, הקסם הדו-כיווני מתעצם עוד יותר: בעוד שקדימה מקדם ההסתעפות הוא $b_{\text{forward}} = 2$ (לכל $k$ יש $2k$ ו-$2k+1$), הרי שלאחור מתרחש נס מתמטי:

החוקיות ההפוכה הדטרמיניסטית:
עבור כל מספר טבעי $n > 1$, קיים מקור אחד ויחיד ממנו הוא נוצר: $$\text{Parent}(n) = \lfloor n / 2 \rfloor = n // 2$$ למשל:
  • אם $n = 11$ (אי-זוגי): $11 // 2 = 5$ (נוצר מ-$2 \times 5 + 1$).
  • אם $n = 10$ (זוגי): $10 // 2 = 5$ (נוצר מ-$2 \times 5$).
מקדם ההסתעפות לאחור הוא בדיוק: $b_{\text{backward}} = 1$!

ההשלכה העצומה: חיפוש אחורנית מהמטרה לעבר השורש 1 אינו מתפצל כלל! זהו מסלול ישר ודטרמיניסטי של חלוקה ב-2: $$11 \xrightarrow{//2} 5 \xrightarrow{//2} 2 \xrightarrow{//2} 1$$ החיפוש הדו-כיווני מוצא את הפתרון באפס חיפושי סרק ובסיבוכיות זמן אופטימלית של: $$O(\log n) = O(d)$$

⚡ 4. שיא העומק: רפורמולציה (Reformulation) דרך ייצוג בינארי ישיר

כאן מתגלה הגאונות האמיתית של מהנדס בינה מלאכותית: החלפת ייצוג הבעיה (Change of Representation) מייתרת לחלוטין את פעולת החיפוש!

מנגנון הפיענוח הבינארי הישיר Zero-Search Algorithm
שלב 1: נמיר את מספר המטרה $G = 11$ לבסיס בינארי:
$11_{10} = \mathbf{1}011_2$
שלב 2: נשמיט את הביט השמאלי ביותר (ה-MSB שהוא תמיד '1' עבור מספר חיובי, ומייצג את שורש העץ $S_0 = 1$):
רצף הפקודות הנותר: $\mathbf{0, 1, 1}$
שלב 3: פירוש הסיביות כפקודות ניווט מדויקות בעץ:
ביט '0': הכפל ב-2 $\implies$ פנה שמאלה בעץ!
ביט '1': הכפל ב-2 והוסף 1 $\implies$ פנה ימינה בעץ!
ניווט ישיר ודטרמיניסטי מהשורש 1: • מתחילים ב-1.
• קוראים ביט ראשון '0': $1 \times 2 = \mathbf{2}$ (פנייה שמאלה).
• קוראים ביט שני '1': $2 \times 2 + 1 = \mathbf{5}$ (פנייה ימינה).
• קוראים ביט שלישי '1': $5 \times 2 + 1 = \mathbf{11}$ (פנייה ימינה).
הגענו ישירות למטרה 11 באפס חיפושים! זמן ריצה: $O(\log n)$ (אורך הייצוג הבינארי).
התובנה ההנדסית העמוקה:

לפני שרצים לכתוב אלגוריתם חיפוש מורכב וזולל משאבים (כמו A* או BFS), מהנדס AI חכם תמיד שואל את עצמו: האם המרחב מאפשר ניסוח מחדש (Reformulation)? כאשר מבינים את המתמטיקה של הבעיה, פעמים רבות ניתן לעקוף את "קללת הממדיות" ולהגיע לפתרון מיידי, כפי שהוכחנו כאן!

🧪

התנסות מעשית: מפענח המבנים הבינאריים וסייר העץ האינסופי

בסימולציה הבאה תוכלו להזין כל מספר מטרה שתרצו (קטן או עצום!), לצפות בעץ החיפוש מתפתח שלב אחר שלב באלגוריתמי BFS, DLS, ו-IDS, לראות את כוחו של החיפוש הדו-כיווני ($b=1$), ולחזות באנימציית הפיענוח הבינארי המנווטת ישירות למטרה ללא שגיאות.

איך לחקור במעבדה?
• הזנת יעד: הזינו מספר (למשל 11, 19, 43 או 156) ולחצו על "עדכן מטרה".
• מצבי אלגוריתם: עברו בין BFS (הסורק שכבות), DLS (הצולל לענף שמאל), IDS (המעמיק איטרטיבית), ו-Binary Reformulation.
• המחשת $b=1$: צפו כיצד החיפוש לאחור מטפס בחלוקה שלמה ב-2 ללא פיצולים.
יחידה 2.3 מידול מרחבי בעיה מורכבים וקבילות היוריסטיקות

מידול בעיות וקבילות: בעיית ששת החצים ומשחק לוח $8\times 8$

💡 המלכודת של "נראה כמו היוריסטיקה טובה"

אחד האתגרים הגדולים בבחינות ובפיתוח מערכות AI הוא תכנון פונקציה היוריסטית $h(n)$ לבעיה חדשה שמעולם לא פגשתם. האינסטינקט הראשוני שלנו תמיד אומר: "בוא נספור כמה אלמנטים נמצאים במצב לא נכון, או נסכום את המרחקים". אך ביחידה זו נלמד דרך שתי בעיות בחינה קלאסיות מדוע האינטואיציה הזו שגויה ומטעה! נכיר את בעיית ששת החצים ונבין מדוע מרחק המינג אינו קביל, וננתח לעומק את משחק לוח $8\times 8$, שבו כל פעולה מייצרת אפקט אדווה (Ripple Effect) המשנה בו-זמנית את מצבן של 4 שכנות סביבה!

🏹 1. בעיית ששת החצים (The Six Arrows Problem)

בבעיה זו נתונים שישה חצים מסודרים בשורה אופקית.

מפרט פורמלי של בעיית החצים:
מצב התחלה ($S_0$): שלושת החצים הראשונים פונים ימינה, שלושת האחרונים שמאלה:
→ → → ← ← ←   (111000)
מצב מטרה ($G$): תבנית סירוגית המתחילה בימינה:
→ ← → ← → ←   (101010)
• אופרטורים חוקיים: היפוך בו-זמני של כיווני שני חצים סמוכים (פעולת NOT על שני ביטים צמודים).
• עלות פעולה: עלות אחידה של $1$ לכל היפוך זוג.
• גודל מרחב המצבים הכולל: $2^6 = \mathbf{64}$ מצבים אפשריים בלבד!
• דרגת הסתעפות (Branching Factor): מתוך שורה של 6 חצים, קיימים בדיוק 5 זוגות סמוכים: (1-2, 2-3, 3-4, 4-5, 5-6). לכן תמיד: $b = \mathbf{5}$.

⚠️ ניתוח היוריסטיקה מוצעת: מרחק המינג (ספירת חצים שגויים)

נניח שהוצעה פונקציה היוריסטית $h(n)$ הסופרת את מספר החצים שאינם תואמים את תבנית המטרה. האם היוריסטיקה זו קבילה (Admissible)?
תשובה: לא! ההיוריסטיקה אינה קבילה בעליל.

דוגמה נגדית (Counterexample):

נניח שהמצב הנוכחי שונה מהמטרה אך ורק בשני חצים סמוכים (למשל, חצים 2 ו-3 שגויים, וכל השאר נכונים).
• היוריסטיקת המינג תספור 2 שגיאות ותחזיר: $h(n) = \mathbf{2}$.
• אולם, מאחר ששני החצים הללו צמודים, פעולת היפוך אחת ויחידה על הזוג (2-3) בעלות של $1$ מתקנת את שני החצים ומביאה אותנו ישירות למטרה!
• העלות האמיתית המינימלית היא: $h^*(n) = \mathbf{1}$.
• מכיוון ש-$h(n) = 2 > h^*(n) = 1$, ההיוריסטיקה מעריכה הערכת יתר (Overestimation) ושוברת את תנאי הקבילות!

תובנה אדריכלית חשובה: מתי אסור להשתמש ב-$A^*$?

במרחב מצבים זעיר של 64 מצבים עם $b=5$, שימוש ב-$A^*$ עם היוריסטיקה מורכבת הוא שגיאת תכנון מערכתית (Over-engineering). אלגוריתם חיפוש לרוחב (BFS) פשוט יסרוק את כל המרחב תוך אלפית השנייה, ימצא את הפתרון האופטימלי בוודאות, ויחסוך את כל תקורת החישוב של תורי עדיפויות וסיכון לשגיאות בהיוריסטיקה!

♟️ 2. משחק לוח משבצות $8\times 8$ עם היפוך צבעים (Exam Passage 2)

שאלת מבחן קלאסית ומעמיקה במיוחד: נתון לוח משובץ בגודל $8\times 8$ (64 משבצות), שבו כל משבצת צבועה בשחור (1) או בלבן (0).

תנאי הניצחון (Goal Test):

מצב שבו לכל משבצת בלוח יש לפחות 2 משבצות שכנות (למעלה, למטה, ימין, שמאל) בעלות צבע זהה לצבע שלה!

$\forall (i,j): \quad x_{ij} \ge 2 \quad (\text{כאשר } x_{ij} \text{ שכנות באותו צבע})$
אופרטורים ועלויות מעבר:

הפיכת הצבע של משבצת בודדת $(i,j)$ על גבי הלוח:

  • • היפוך מלבן לשחור ($W \to B$): עלות = מספר השורה $i \in \{1,\dots,8\}$.
  • • היפוך משחור ללבן ($B \to W$): עלות = מספר העמודה $j \in \{1,\dots,8\}$.
ניתוח ממדי מרחב המצבים:
גודל המרחב:
2⁶⁴ מצבים
כ-1.84×10¹⁹ אפשרויות
דרגת הסתעפות:
b = 64
ניתן להפוך כל משבצת
עומק עץ אפקטיבי:
m = 64
היפוך כפול מתבטל

🏆 הוכחה מתמטית ריגורוזית: קיום צמתי מטרה בעומק 32 ומטה!

טענה (מופיעה בבחינות): מובטח כי מכל מצב התחלתי שרירותי על הלוח, קיים מצב מטרה חוקי בעומק של לכל היותר 32 צעדים בעץ החיפוש!

הוכחה בארבעה שלבים:
1. לוח מונוכרומטי הוא מצב מטרה חוקי: נתבונן בלוח שבו כל 64 המשבצות צבועות באותו צבע (כולו לבן או כולו שחור).
  • למשבצת פינתית יש בדיוק 2 שכנות, ושתיהן באותו הצבע $\implies 2 \ge 2$ (עומד בתנאי!).
  • למשבצת על השפה יש 3 שכנות באותו הצבע $\implies 3 \ge 2$ (עומד בתנאי!).
  • למשבצת פנימית יש 4 שכנות באותו הצבע $\implies 4 \ge 2$ (עומד בתנאי!).
לכן, לוח אחיד בצבעו מהווה מצב מטרה חוקי לחלוטין!
2. חלוקת המשבצות לפי עקרון שובך היונים:
נסמן ב-$W$ את מספר המשבצות הלבנות ובו-$B$ את מספר המשבצות השחורות בלוח ההתחלתי. מאחר שבסך הכל יש 64 משבצות: $$W + B = 64 \implies \min(W, B) \le 32$$
3. אסטרטגיית הפיכת צבעי המיעוט:
נבחר להפוך את צבען של כל משבצות המיעוט אל צבע הרוב. מאחר שמספר משבצות המיעוט אינו עולה על 32, נדרשות לכל היותר 32 פעולות היפוך בלבד כדי להגיע למצב שבו כל הלוח אחיד בצבעו!
מ.ש.ל: קיים תמיד מסלול אל צומת מטרה באורך $\le 32$.

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

מוצעת ההיוריסטיקה הבאה: סוכמים לכל משבצת $(i,j)$ את הפער $(2 - x_{ij})$ במידה ויש לה פחות מ-2 שכנות באותו צבע:

$$h(n) = \sum_{(i,j): \, x_{ij} < 2} (2 - x_{ij})$$

האם היוריסטיקה זו קבילה (Admissible)?
תשובה חד-משמעית: לא! ההיוריסטיקה אינה קבילה.

הוכחה ודוגמה נגדית מפורטת (אפקט האדווה):

נניח לוח שבו כל המשבצות שחורות, למעט משבצת לבנה בודדת ומבודדת בשורה 1, עמודה 2:

  • עבור המשבצת הלבנה הזו, יש $x = 0$ שכנות לבנות, ולכן היא תורמת להיוריסטיקה: $2 - 0 = \mathbf{2}$.
  • בנוסף, עבור כל אחת מ-4 השכנות השחורות שלה, הימצאות המשבצת הלבנה גרעה מהן שכן שחור. אם לאחת השכנות הללו יש רק שכן שחור אחד נוסף ($x=1$), היא תתרום להיוריסטיקה: $2 - 1 = \mathbf{1}$.
  • לפיכך, ערך ההיוריסטיקה המצטבר עבור הלוח יהיה: $h(n) \ge 2 + 1 = \mathbf{3}$.
אבל מהי העלות האמיתית $h^*(n)$?
בפעולה בודדת אחת של היפוך המשבצת הלבנה לשחורה ($W \to B$) בשורה $1$, עלות הצעד היא בדיוק 1 (מספר השורה)! היפוך זה פותר באחת את הבעיה עבור המשבצת עצמה ומשפר את תנאי השכנות של כל 4 שכנותיה במקביל (כל הלוח הופך לשחור אחיד וחוקי!).
לכן העלות האמיתית היא: $h^*(n) = \mathbf{1}$.

מכיוון ש-$h(n) \ge 3 > h^*(n) = 1$, ההיוריסטיקה מעריכה הערכת יתר (Overestimation) ולכן אינה קבילה!

🧪

התנסות מעשית: מעבדת היוריסטיקות (Heuristics Lab) ולוח $8\times 8$

בסימולציה זו תוכלו לשחק ישירות על לוח ה-$8\times 8$, להפוך צבעי משבצות בקליק, לחזות באנימציית "אדוות ההשפעה" (Ripple Effect) על 4 השכנות, לבחון את עלויות הפעולה המשתנות לפי שורה/עמודה, וללחוץ על כפתור "טען דוגמה נגדית" כדי לראות במו עיניכם מתי $h(n) > h^*(n)$ והקבילות קורסת!

בדיקות מומלצות במעבדה:
• טעינת דוגמה נגדית: לחצו על "טען אי מבודד" וראו כיצד ההיוריסטיקה מקבלת ערך גבוה, בעוד שצעד בודד בשורה 1 פותר את הלוח בעלות 1!
• מצב 6 החצים: החליפו תצוגה ל"בעיית 6 החצים" ובדקו כיצד היפוך זוג סמוך מתקן 2 שגיאות בצעד אחד.
יחידה 2.4 מעקב אלגוריתמי מעמיק בגרף בחינה

מעקב וניתוח אלגוריתמי בגרף מבחן ובחינת עקביות

💡 איך לבצע מעקב יבש אלגוריתמי בדיוק מוחלט

שאלות מעקב יבש (Traces) על גרף מרובה צמתים הן שאלות "מתנה" בבחינה – אך רק אם עובדים בשיטה קרה ומסודרת ללא קיצורי דרך! ביחידה זו ננתח לפרטי פרטים את גרף המבחן המלא בן 10 הצמתים (מתוך Passage 8). נריץ עליו בזה אחר זה את ארבעת אלגוריתמי החיפוש המרכזיים: BFS, UCS, Greedy Best-First, ו-$A^*$. נראה בדיוק מי מוכנס לתור, מי נשלף ראשון, כיצד שוברים שוויונות אלפביתית, ולבסוף נוכיח מתמטית מדוע ההיוריסטיקה הנתונה בגרף היא קבילה לחלוטין אך אינה עקבית!

🗺️ 1. נתוני גרף המבחן (Exam Graph Specification)

נתון גרף מכוון הכולל צומת התחלה $S$, שני צמתי מטרה $G_1, G_2$, וערכי היוריסטיקה $h(n)$ הרשומים לצד כל צומת:

נתוני הצמתים והקשתות בגרף 10 Nodes, 12 Edges
ערכי ההיוריסטיקה $h(n)$:
• $S(8), \quad A(9), \quad B(1), \quad C(7)$
• $D(4), \quad E(1), \quad F(5), \quad H(1)$
• $G_1(0), \quad G_2(0) \quad (\text{צמתי מטרה})$
עלויות הקשתות והמעברים:
• $S \to A = 3, \quad S \to B = 1, \quad S \to C = 5$
• $B \to D = 4, \quad D \to B = 4, \quad D \to S = 3$
• $A \to H = 10, \quad A \to E = 7, \quad E \to H = 2$
• $C \to G_2 = 11, \quad G_2 \to F = 0$
• $D \to G_1 = 5, \quad F \to D = 1, \quad F \to G_1 = 5$
* הנחות העבודה במבחן: משתמשים ב-Explored Set למניעת חזרות ומעגלים. במקרה של שוויון בעדיפות, שוברים שוויון לפי סדר אלפביתי.

⚡ 2. פירוק מעקב מלא צעד-אחר-צעד (Four Algorithms Dry Trace)

א. חיפוש לרוחב (Breadth-First Search - BFS) Queue (FIFO)

BFS מפתח צמתים לפי סדר הגעתם לתור (עומק עץ), ואינו מתחשב במשקלי הקשתות או בהיוריסטיקה:

  1. הרחבת $S$: יורשיו מתווספים לפי סדר אלפביתי. חזית: $\{A, B, C\}$.
  2. הרחבת $A$: יורשיו $\{E, H\}$. חזית כעת: $\{B, C, E, H\}$.
  3. הרחבת $B$: יורשו $\{D\}$. חזית כעת: $\{C, E, H, D\}$.
  4. הרחבת $C$: יורשו $\{G_2\}$. חזית כעת: $\{E, H, D, G_2\}$.
  5. הרחבת $E$: יורשו $H$ כבר בחזית. חזית כעת: $\{H, D, G_2\}$.
  6. הרחבת $H$: אין יורשים חוקיים. חזית כעת: $\{D, G_2\}$.
  7. הרחבת $D$: יורשו $\{G_1\}$. חזית כעת: $\{G_2, G_1\}$.
  8. הרחבת $G_2$: נשלף צומת מטרה! עצירה וסיום.
סדר ההרחבה המלא: $S \to A \to B \to C \to E \to H \to D \to G_2$
המסלול שנמצא: $S \to C \to G_2$ בעלות מצטברת: $5 + 11 = \mathbf{16}$ (סאב-אופטימלי יקר!).
ב. חיפוש בעלות אחידה (Uniform-Cost Search - UCS) Priority Queue by $g(n)$

UCS ממיין את החזית בקפדנות לפי עלות המסלול המצטברת $g(n)$ מהשורש:

  1. הרחבת $S$ ($g=0$): יורשים $B(g=1), A(g=3), C(g=5)$. חזית: $\{B(1), A(3), C(5)\}$.
  2. הרחבת $B$ ($g=1$): יורש $D$ עם $g = 1 + 4 = 5$. חזית: $\{A(3), C(5), D(5)\}$.
  3. הרחבת $A$ ($g=3$): יורשים $E(g=3+7=10), H(g=3+10=13)$. חזית: $\{C(5), D(5), E(10), H(13)\}$.
  4. הרחבת $C$ ($g=5$): יורש $G_2$ עם $g = 5 + 11 = 16$. חזית: $\{D(5), E(10), H(13), G_2(16)\}$.
  5. הרחבת $D$ ($g=5$): יורש $G_1$ עם $g = 5 + 5 = 10$. חזית: $\{E(10), G_1(10), H(13), G_2(16)\}$.
  6. הרחבת $E$ ($g=10$): מוצא מסלול זול יותר ל-$H$ ($g = 10 + 2 = 12$). מעדכן את $H$. חזית: $\{G_1(10), H(12), G_2(16)\}$.
  7. הרחבת $G_1$ ($g=10$): נשלף צומת מטרה! עצירה וסיום.
סדר ההרחבה המלא: $S \to B \to A \to C \to D \to E \to G_1$
המסלול שנמצא: $S \to B \to D \to G_1$ בעלות אופטימלית: $1 + 4 + 5 = \mathbf{10}$!
ג. חיפוש חמדן ראשון-הטוב-ביותר (Greedy Best-First Search) Priority Queue by $h(n)$

החיפוש החמדן מסתמך אך ורק על הציון היוריסטי $h(n)$ ומתעלם מכל עלות ששולמה בעבר:

  1. הרחבת $S$ ($h=8$): יורשים $B(h=1), C(h=7), A(h=9)$. חזית: $\{B(1), C(7), A(9)\}$.
  2. הרחבת $B$ ($h=1$): יורש $D(h=4)$. חזית כעת: $\{D(4), C(7), A(9)\}$.
  3. הרחבת $D$ ($h=4$): יורש $G_1(h=0)$. חזית כעת: $\{G_1(0), C(7), A(9)\}$.
  4. הרחבת $G_1$ ($h=0$): נשלף צומת מטרה! עצירה וסיום.
סדר ההרחבה המלא: $S \to B \to D \to G_1$ (סריקה קצרה ומהירה ביותר של 4 צמתים בלבד!).
המסלול שנמצא: $S \to B \to D \to G_1$ בעלות: $\mathbf{10}$.
ד. אלגוריתם $A^*$ המשולב Priority Queue by $f(n) = g(n) + h(n)$

$A^*$ משקלל את העבר עם העתיד וממיין לפי ערך $f(n)$:

  1. הרחבת $S$ ($f = 0 + 8 = 8$): יורשים:
    • $B: g=1, h=1 \implies f(B) = 1 + 1 = \mathbf{2}$
    • $A: g=3, h=9 \implies f(A) = 3 + 9 = \mathbf{12}$
    • $C: g=5, h=7 \implies f(C) = 5 + 7 = \mathbf{12}$
    חזית: $\{B(f=2), A(f=12), C(f=12)\}$.
  2. הרחבת $B$ ($f=2$): יורש $D$ עם $g=1+4=5, h=4 \implies f(D) = 5 + 4 = \mathbf{9}$.
    חזית כעת: $\{D(f=9), A(f=12), C(f=12)\}$.
  3. הרחבת $D$ ($f=9$): יורש $G_1$ עם $g=5+5=10, h=0 \implies f(G_1) = 10 + 0 = \mathbf{10}$.
    חזית כעת: $\{G_1(f=10), A(f=12), C(f=12)\}$.
  4. הרחבת $G_1$ ($f=10$): נשלף צומת מטרה! עצירה וסיום.
סדר ההרחבה המלא: $S \to B \to D \to G_1$
המסלול שנמצא: $S \to B \to D \to G_1$ בעלות אופטימלית: $\mathbf{10}$!

⚖️ 3. הוכחה מתמטית: האם ההיוריסטיקה בגרף קבילה ועקבית?

✓ א. הוכחת קבילות (Admissibility: $h(n) \le h^*(n)$)
  • $h^*(G_1) = 0 \ge h(G_1) = 0$ (מתקיים).
  • $h^*(G_2) = 0 \ge h(G_2) = 0$ (מתקיים).
  • $h^*(D) = 5 \ge h(D) = 4$ (מתקיים).
  • $h^*(B) = 4 + 5 = 9 \ge h(B) = 1$ (מתקיים).
  • $h^*(C) = 11 \ge h(C) = 7$ (מתקיים).
  • $h^*(S) = 1 + 4 + 5 = 10 \ge h(S) = 8$ (מתקיים).
  • ומה לגבי צמתים $A, E, H$?
    מצמתים אלו אין שום מסלול אפשרי אל אף אחד מצמתי המטרה! לפיכך, העלות האמיתית להגעה למטרה היא אינסופית: $$h^*(A) = h^*(E) = h^*(H) = \infty$$ ומכיוון ש-$\infty \ge h(n)$, התנאי מתקיים גם עבורם!
מסקנה: $h$ קבילה לחלוטין בכל צומת וצומת בגרף!
✗ ב. הוכחת חוסר עקביות (Inconsistency)

נבדוק את אי-שוויון המשולש עבור הקשת $S \to B$ שעלותה $c(S,B) = 1$:

$$h(S) = 8, \quad c(S,B) = 1, \quad h(B) = 1$$ $$h(S) \le c(S,B) + h(B) \implies 8 \le 1 + 1 = 2 \quad \text{\textbf{סתירה!}}$$

ההפרש בהערכה ההיוריסטית הוא: $$h(S) - h(B) = 8 - 1 = 7 > c(S,B) = 1$$ ההערכה צונחת ב-7 יחידות לאורך קשת שעלותה 1 בלבד!

מסקנה: ההיוריסטיקה אינה עקבית (אי-שוויון המשולש מופר בגסות)!

🏃 4. חיפוש חמדן פורמלי (Greedy Best-First Search): פסאודוקוד ומגבלות תיאורטיות

אלגוריתם חיפוש חמדן (Greedy Best-First Search) מונחה על ידי עקרון פשוט: בכל שלב, הרחב את הצומת שנראה הקרוב ביותר למטרה לפי פונקציית ההיוריסטיקה $h(n)$, תוך התעלמות מוחלטת מעלות המסלול שנצברה בעבר: $$f(n) = h(n)$$

פסאודוקוד: אלגוריתם Best-first(init)
function Best-first(init):
    OPEN = PriorityQueue() sorted by h(n) ascending
    CLOSE = Set()
    
    OPEN.insert(init)
    
    while not OPEN.isEmpty():
        n = OPEN.extractMin()  // node with lowest h(n)
        
        if isGoal(n):
            return constructPath(n)  // Return solution path
            
        CLOSE.add(n)
        
        for each successor n' of n:
            // Loop prevention check
            if n' not in OPEN and n' not in CLOSE:
                parent(n') = n
                OPEN.insert(n')
                
    return FAILURE
שלמות ואופטימליות (Completeness & Optimality)
• שלמות: שלם במרחב מצבים סופי עם בדיקת מעגלים ($\text{CLOSE}$). במרחב אינסופי, אינו שלם – הוא עלול לדהור לאורך ענף אינסופי ללא מוצא המציג ערכי $h$ אופטימיים מטעים ("מרדף שווא").
• אופטימליות: אינו אופטימלי כלל! הוא עלול לבחור מסלול עוקף יקר להחריד רק כי כל צעד נראה מפתה ומבטיח היוריסטית.
סיבוכיות ורגישות להערכות שגויות
• סיבוכיות זמן ומקום: $O(b^m)$ במקרה הגרוע (כאשר ההיוריסטיקה מטעה). אך עם היוריסטיקה איכותית ומדויקת, הסיבוכיות צונחת ל-$O(b \cdot d)$.
• רגישות: האלגוריתם פגיע מאוד למכשולים וקירות (Cul-de-sacs); הוא "נצמד" לקיר הקרוב ביותר ליעד ומתקשה לסגת ממנו.

⚖️ 5. אלגוריתם $A^*$ ממושקל (Weighted A*) וחיפוש $\epsilon$-קביל (Bounded Suboptimality)

לעיתים קרובות בעולם האמיתי, אנו מוכנים להתפשר מעט על שלמות האופטימליות (למשל, להסתפק במסלול היקר ב-10% מהאופטימלי) בתמורה לקיצוץ אדיר של 95% מזמן החישוב והזיכרון! לשם כך פותח אלגוריתם $A^*$ ממושקל (Weighted A*), המשתמש בפונקציית הערכה פרמטרית עם משקל $w \in [0, 1]$:

$$f_w(n) = (1 - w) \cdot g(n) + w \cdot h(n), \qquad w \in [0, 1]$$
w = 0
חיפוש בעלות אחידה (UCS)

$$f_0(n) = g(n)$$ אופטימליות מוחלטת, עיוור לעתיד, סורק צמתים רבים ואיטי.

w = 0.5
אלגוריתם $A^*$ הקלאסי

$$f_{0.5}(n) = 0.5(g(n) + h(n))$$ איזון מושלם בין עבר לעתיד. קביל ואופטימלי (שקול ל-$g+h$).

w = 1
חיפוש חמדן (Greedy)

$$f_1(n) = h(n)$$ מהיר ותוקפני ביותר, אך מאבד כל הבטחה לאופטימליות.

משפט הקבילות ו-$\epsilon$-קבילות ב-Weighted A*:
  • עבור $w \le 0.5$: אם $h$ קבילה, האלגוריתם קביל ואופטימלי לחלוטין (כי המשקל היחסי הניתן ל-$h$ אינו עולה על משקל $g$).
  • עבור $w > 0.5$: האלגוריתם מאבד אופטימליות מוחלטת, אך מקיים תכונה מופלאה הנקראת $\epsilon$-קבילות ($\epsilon$-Admissibility): $$Cost(\text{Solution}) \le (1 + \epsilon) \cdot C^*, \qquad \text{where } \epsilon = \frac{w}{1 - w} - 1 = \frac{2w - 1}{1 - w}$$
  • דוגמה מספרית מהמבחן: אם בוחרים $w = 0.6$: $$\epsilon = \frac{2(0.6) - 1}{1 - 0.6} = \frac{0.2}{0.4} = 0.5$$ האלגוריתם מתחייב למצוא פתרון שעלותו לא תעלה על $1.5 \cdot C^*$ (לא יותר מ-50% מעל האופטימום), תוך הפחתת כמות הצמתים המפותחים במאות אחוזים!

🎛️ 6. שקלול דינמי (Dynamic Weighting): מניעת הסתבכות בענפים עמוקים

ב-Weighted A* קבוע עם $w > 0.5$, אם ההיוריסטיקה שוגה בעומק העץ, האלגוריתם עלול "להיתקע" בענף שגוי ועמוק מבלי לחזור אחורה. כדי לפתור זאת, הוצע מנגנון שקלול דינמי (Dynamic Weighting), שבו משקל ההיוריסטיקה משתנה כפונקציה של עומק הצומת $d(n)$:

$$f_{dw}(n) = g(n) + h(n) + \epsilon \left(1 - \frac{d(n)}{N}\right) h(n)$$
הפרמטרים וההיגיון ההנדסי של הנוסחה:
  • $d(n)$: עומק הצומת הנוכחי מהשורש.
  • $N$: הערכה לחסם עליון על עומק פתרון המטרה האופטימלי ($d(G^*) \le N$).
  • $\epsilon \ge 0$: מקדם עודף משקל היוריסטי.
בתחילת הדרך ($d(n) \to 0$): האיבר $\left(1 - \frac{d(n)}{N}\right) \approx 1$.
פונקציית ההערכה הופכת ל-$g(n) + (1+\epsilon)h(n)$. האלגוריתם מתנהג בחמדנות יתרה וטס קדימה במהירות עצומה!
בעומק העץ ($d(n) \to N$): האיבר $\left(1 - \frac{d(n)}{N}\right) \to 0$.
המשקל העודף מתאפס, והפונקציה מתכנסת חזרה ל-$f(n) = g(n) + h(n)$. האלגוריתם חוזר להיות $A^*$ קלאסי ומבטיח דיוק מרבי ליד היעד!

🔄 7. אלגוריתם מעמיק איטרטיבי מיודע ($IDA^*$ - Iterative Deepening A*)

החיסרון הקטלני של $A^*$ בעולם האמיתי אינו זמן הריצה – אלא צוואר בקבוק הזיכרון (RAM): שמירת כל הצמתים שנוצרו ברשימת OPEN גוזלת זיכרון מעריכי $O(b^d)$ שמפיל שרתים תוך שניות. אלגוריתם $IDA^*$ (Iterative Deepening A*) מציג את השילוב המנצח: יעילות זיכרון לינארית $O(b \cdot d)$ כמו של DFS, יחד עם אופטימליות מלאה של $A^*$!

כיצד $IDA^*$ פועל? מחסום ה-Cutoff Threshold:

בניגוד ל-IDS עיוור המגביל את עומק העץ ($l = 0, 1, 2 \dots$), אלגוריתם $IDA^*$ קובע חסם סף על ערך ה-$f$ (Threshold Bound):

  1. איטרציה ראשונה: החסם נקבע להיות ההיוריסטיקה של השורש: $\text{bound} = h(s_0)$.
  2. מהלך האיטרציה: מריצים חיפוש DFS מוגבל סף (הנקרא DFS-C). כל ענף שבו $f(n) > \text{bound}$ נגזם מיד ואינו מפותח!
  3. הקביעה הגאונית של הסף הבא: אם היעד לא נמצא, הסף הבא נקבע להיות הערך המינימלי מבין כל ערכי ה-$f$ של הצמתים שנגזמו באיטרציה הנוכחית! (ולא סתם $\text{bound} + 1$).
פסאודוקוד מלא: אלגוריתמי IDA* ו-DFS-C
function IDA_star(root):
    bound = h(root)
    while true:
        (status, val) = DFS_C(root, 0, bound)
        if status == FOUND:
            return val  // Optimal solution path found!
        if val == INFINITY:
            return FAILURE  // Exhausted space without reaching goal
        bound = val  // Advance threshold to smallest exceeded f-value

function DFS_C(n, g, bound):
    f = g + h(n)
    if f > bound:
        return (NOT_FOUND, f)  // Pruned by threshold: report exceeded f
        
    if isGoal(n):
        return (FOUND, constructPath(n))
        
    min_cutoff = INFINITY
    for each successor n' of n with step cost c(n, n'):
        (status, val) = DFS_C(n', g + c(n, n'), bound)
        if status == FOUND:
            return (FOUND, val)
        if val < min_cutoff:
            min_cutoff = val  // Track smallest f exceeding current bound
            
    return (NOT_FOUND, min_cutoff)
יתרונות מרכזיים של $IDA^*$:
✓ סיבוכיות מקום לינארית: $O(b \cdot d)$ בלבד! ניתן לפתור באמצעותו בעיות ענק (כמו 15-Puzzle) שקורסות ב-$A^*$ רגיל מחוסר RAM.
✓ אופטימליות מלאה: אם $h(n)$ קבילה, הפתרון הראשון שנמצא מובטח להיות אופטימלי ($C^*$).
החיסרון ומקרה הקצה הבעייתי:
✗ ריבוי ערכי $f$ שונים: כאשר משקלי הקשתות או ההיוריסטיקה הם מספרים ממשיים רציפים, בכל איטרציה הסף עלול לעלות בשיעור זעיר ולפתוח רק צומת אחד נוסף! במקרה זה מתבצעות $N$ איטרציות וזמן הריצה מתנפח לרמה ריבועית ומעלה.

8 אלגוריתמי חיפוש מוגבלי-זיכרון: $RBFS$ ו-$SMA^*$ (Memory-Bounded Heuristic Search)

מעבר ל-$IDA^*$, הספר (Russell & Norvig, פרק 3) מציג שני אלגוריתמים בולטים שמטרתם להתגבר על מגבלת הזיכרון המעריכית של $A^*$ תוך שמירה על יתרונות היוריסטיים:

1. חיפוש Best-First רקורסיבי ($RBFS$) Space: $O(b \cdot d)$

אלגוריתם רקורסיבי שמחקה את התנהגותו של $A^*$ הסטנדרטי אך צורך זיכרון לינארי בלבד $O(b \cdot d)$.

  • מנגנון ה-$f\_limit$: האלגוריתם עוקב אחר ערך ה-$f$ של האלטרנטיבה הטובה ביותר השנייה הזמינה לאבותיו של הצומת הנוכחי.
  • נסיגה לאחור וגיבוי ערכים (Backing up): כאשר כל היורשים של הצומת הנוכחי חורגים מה-$f\_limit$, האלגוריתם נסוג לאחור, אך שומר בצומת האב את ערך ה-$f$ של היורש הטוב ביותר שנשכח!
  • יתרון ואופטימליות: מוצא מסלול אופטימלי אם $h$ קבילה.
  • חיסרון: "תזזיתיות" (Thrashing) – פיתוח מחדש חוזר ונשנה של צמתים כאשר ערכי ה-$f$ של ענפים מתחרים קרובים זה לזה.
2. אלגוריתם $SMA^*$ (Simplified Memory-Bounded $A^*$) Space: $O(M)$ קבוע

מנצל במלואו את כל הזיכרון הפנוי בשרת (מגבלה של $M$ צמתים ב-RAM) ולא קילובייט פחות.

  • פעולה בתוך מגבלת הזיכרון: פועל בדיוק כמו $A^*$ כל עוד הזיכרון אינו מלא.
  • מחיקת העלה הגרוע ביותר (Drop Worst): כאשר הזיכרון מתמלא, האלגוריתם מוחק מתור העדיפויות את העלה בעל ערך ה-$f$ הגבוה ביותר (הכי פחות מבטיח).
  • גיבוי ערך לתוך האב (Backed-up f-cost): לפני המחיקה, ערך ה-$f$ של הבן שנמחק נרשם בצומת האב שלו! אם בעתיד כל שאר המסלולים יתבררו כגרועים עוד יותר, האב יוכל לשחזר ולפתח מחדש את הבן שנמחק.
  • שלמות ואופטימליות: שלם אם עומק הפתרון $d \le M$. אופטימלי אם המסלול האופטימלי כולו נכנס ב-$M$ צמתים.
אלגוריתם סיבוכיות זיכרון שלמות (Completeness) אופטימליות ($h$ קבילה) עומס פיתוח חוזר (Re-expansion)
$A^*$ (סטנדרטי) $O(b^d)$ (מעריכי קורס!) כן כן אפס (אם $h$ עקבית)
$IDA^*$ $O(b \cdot d)$ (לינארי) כן כן בינוני עד גבוה (בכל איטרציה)
$RBFS$ $O(b \cdot d)$ (לינארי) כן כן גבוה (Thrashing בין ענפים)
$SMA^*$ $O(M)$ (מוגבל ע"י RAM) כן (אם $d \le M$) כן (אם המסלול $\le M$) נמוך אם $M$ גדול; תזזיתי אם $M$ קטן מדי
🧪

התנסות מעשית: מרוץ האלגוריתמים ומעקב גרף המבחן

בסימולציה הבאה תוכלו לצפות בגרף המבחן המלא בן 10 הצמתים, להריץ עליו במקביל או צעד אחר צעד את BFS, UCS, Greedy, ו-$A^*$, לעקוב בזמן אמת אחר תכולת תור העדיפויות וה-Explored Set, וללחוץ על כפתור "בדיקת עקביות" כדי לראות את הקשת $S \to B$ מהבהבת באדום עם חישוב אי-שוויון המשולש!

בדיקות מומלצות בסימולטור:
• מרוץ האלגוריתמים: לחצו על "מרוץ כל האלגוריתמים" והשוו בין מספר הצמתים שפותחו ב-UCS לעומת Greedy ו-$A^*$.
• בחינת עקביות גרפית: ראו כיצד האלגוריתם מסמן את ערכי ה-$f$ ואת הקשת השוברת מונוטוניות.
יחידה 2.5 פרדיגמת החיפוש המקומי וטיפוס גבעה

פרדיגמת החיפוש המקומי: טיפוס הרים וגרסאותיו

💡 כשהמסלול אינו מעניין – רק היעד קובע!

עד כה, בכל אלגוריתמי החיפוש שלמדנו (BFS, DFS, UCS, $A^*$), החזקנו בזיכרון עצי חיפוש שלמים כדי לשחזר את מסלול הפעולות המדויק מההתחלה עד הסוף. אבל חישבו על בעיות רבות בעולם האמיתי: בעיית $N$ המלכות, שיבוץ מערכת שעות שנתית באוניברסיטה, תכנון מעגלים מודפסים (VLSI), או קיפול חלבונים בביולוגיה. בבעיות אלו, המסלול שבו סודרו המלכות אינו מעניין איש! כל מה שמעניין אותנו הוא להגיע לקונפיגורציה הסופית הטובה ביותר. כאן נכנסת פרדיגמת החיפוש המקומי (Local Search): מוחקים את כל היסטוריית העבר, שומרים בזיכרון רק את המצב הנוכחי ($O(1)$ זיכרון!), ומטפסים לעבר הפסגה.

⛰️ 1. עקרונות היסוד של חיפוש מקומי (Local Search Principles)

בניגוד לחיפוש קלאסי, בחיפוש מקומי פועלים תחת המאפיינים הבאים:

סיבוכיות מקום מזערית
O(1) Memory

מחזיק רק את המצב הנוכחי ($State$). אין רשימת חזית, אין רשימת סגורים ואין שמירת ענפי עץ.

פונקציית מטרה / טיב
Objective / Fitness

לכל מצב מחושב ציון $f(s)$. במקסימיזציה שואפים לפסגה הגבוהה ביותר, ובמינימיזציה (Cost) שואפים לשפל.

תנועה במרחב
Neighborhood Moves

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

🧗 2. חמש הווריאציות המרכזיות של אלגוריתם טיפוס גבעה (Hill-Climbing)

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

1. טיפוס בעלייה התלולה ביותר (Steepest Ascent Hill-Climbing - SAHC) Greedy Best

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

2. טיפוס עם מהלכי צד (SAHC with Sideways Moves) Plateau Crossing

כיצד פועל: מאפשר מעבר לשכנים בעלי ערך שווה בדיוק ($\Delta E = 0$), כדי לאפשר לאלגוריתם "לזחול" על פני מישורים (Plateaus) או כתפיים (Shoulders) בתקווה למצוא שיפוע עלייה חדש.
המנגנון ההכרחי: כדי למנוע לולאה אינסופית על גבי המישור, חובה לקבוע חסם עליון קשיח (Limit) למספר מהלכי הצד הרצופים (למשל, עד 100 מהלכי צד). אם החסם נחצה – האלגוריתם נכנע ועוצר.

3. בחירה ראשונה (First-Choice Hill-Climbing) Fast & Economical

כיצד פועל: במקום לייצר ולמיין את כל אלפי השכנים, הוא מייצר שכנים באופן אקראי בזה אחר זה. ברגע שהוא נתקל בשכן הראשון שמשפר את המצב הנוכחי ($\Delta E > 0$), הוא מבצע את המעבר מיד!
מתי נשתמש: חיוני במרחבים בעלי מקדם הסתעפות עצום (עשרות אלפי שכנים), שבהם עלות הערכת כל השכנים משתקת את המחשב.

4. טיפוס סטוכסטי (Stochastic Hill-Climbing) Weighted Probability

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

$$P_i = \frac{|\Delta v_i|}{\sum_j |\Delta v_j|}$$

יתרון: מאזן בין ניצול מידע (Exploitation) לבין חקירה מגוונת (Exploration) ומסייע להימנע מכיסי מקסימום צרים.

5. אתחול אקראי חוזר (Random-Restart Hill-Climbing) Complete in Finite Spaces

כיצד פועל: מתגבר על בעיית המקסימום המקומי באמצעות סדרת ריצות עצמאיות: בכל פעם שטיפוס גבעה נתקע במקסימום מקומי, מאתחלים את המערכת ממצב התחלתי אקראי חדש לגמרי, וחוזרים חלילה עד למציאת המטרה.
משפט מתמטי חשוב: אם ההסתברות להגיע למקסימום הגלובלי ממצב התחלה אקראי היא $p > 0$, תוחלת מספר האתחולים הנדרשת עד להצלחה היא:

$$E[\text{restarts}] = \frac{1}{p}$$

במרחב מצבים סופי, אלגוריתם זה הוא שלם (Complete) בהסתברות 1!

⚠️ 3. המכשולים הטופולוגיים במרחבי חיפוש מקומי

שלושת המכשולים המרכזיים שמכשילים אלגוריתמי טיפוס גבעה פשוטים:

🏔️ מקסימום מקומי (Local Maxima)

פסגה הגבוהה מכל שכנותיה הישירות, אך נמוכה משמעותית מהפסגה הגלובלית האמיתית. כל צעד ממנה מהווה ירידה, ולכן האלגוריתם נכלא בה ללא מוצא.

〰️ רכס צר (Ridge)

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

🏜️ מישור שטוח (Plateau / Shoulder)

אזור נרחב שבו לכל השכנים יש ציון זהה לחלוטין ($\Delta E = 0$). אין שום גרדיאנט המכוון את תנועת האלגוריתם, מה שעלול להוביל לשוטטות סרק אינסופית.

🧪

התנסות מעשית: זירת החיפוש המקומי והנוף הטופולוגי (Simulation Arena)

בסימולציה הבאה מוצגת מפת גבהים מרובת פסגות (הכוללת פסגות מקומיות, מישורים ורכסים). תוכלו לשגר סוכני טיפוס הרים שונים (Steepest Ascent, Sideways Moves, Simulated Annealing, ו-Local Beam Search), לצפות בזמן אמת כיצד החמדן נתקע במקסימום מקומי, ואיך מטא-היוריסטיקות מתקדמות נחלצות ומגיעות לפסגה הגלובלית!

מה מומלץ לבדוק?
• צפייה בתקיעה: הפעילו את Steepest Ascent וראו כיצד הסוכן ננעל בגבעה הראשונה ועוצר.
• מהלכי צד: עברו ל-Sideways Moves ובדקו את מונה הצעדים עד להגעה לחסם ה-Limit.
יחידה 2.6 מטא-היוריסטיקות מתקדמות בהשראת הפיזיקה והביולוגיה

מטא-היוריסטיקות מתקדמות: חישול מדומה וחיפוש אלומה

💡 כשהאלגוריתם שואב השראה מתנורי פלדה ומתורת האבולוציה

כיצד נחלצים ממלכודת מקסימום מקומי מבלי לאפס את החיפוש בכל פעם מחדש? חוקרי הבינה המלאכותית פנו לשני תחומי מדע עתיקים: התרמודינמיקה (תורת הפיזיקה הסטטיסטית) והביולוגיה האבולוציונית. ביחידה זו נלמד על חישול מדומה (Simulated Annealing) – אלגוריתם המאפשר לבצע "צעדים גרועים" בהסתברות מבוקרת טמפרטורה, ועל חיפוש אלומה (Local Beam Search) – המנהל צי של $k$ סוכנים במקביל ומגייס משאבים לאזורים פוריים, לצד גרסתו הסטוכסטית המצילה אותו מאובדן גיוון קטלני!

🔥 1. חישול מדומה (Simulated Annealing - SA)

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

מנגנון קבלת ההחלטות בחישול מדומה:
בכל צעד נבחר שכן אקראי $n'$ ומחושב ההפרש: $\Delta E = f(n') - f(n)$.
• אם השכן טוב יותר ($\Delta E > 0$): המעבר מתבצע תמיד בוודאות ($P = 1$)!
• אם השכן גרוע יותר ($\Delta E \le 0$): המעבר אינו נפסל אוטומטית! הוא מתבצע בהסתברות בולצמן:
$P = e^{\frac{\Delta E}{T}}$
כאשר $T > 0$ הוא פרמטר הטמפרטורה הנוכחית של המערכת.
ההתנהגות המתמטית של לוח הזמנים (Cooling Schedule):

הטמפרטורה $T$ יורדת בהדרגה עם התקדמות הזמן לפי פונקציית דעיכה (למשל: $T_{k+1} = \alpha T_k$ כאשר $0.85 \le \alpha < 1$):

  • בתחילת החיפוש ($T$ גבוה מאוד): היחס $\frac{\Delta E}{T} \approx 0 \implies P \approx e^0 = \mathbf{1}$. האלגוריתם מקבל כמעט כל צעד רע, ומתנהג כמו הילוך אקראי (Random Walk) החוקר את מרחב המצבים לרוחבו ומדלג בקלות מעל פסגות ומכשולים!
  • בסוף החיפוש ($T \to 0$): עבור מהלך רע מתקיים $\frac{\Delta E}{T} \to -\infty \implies P \approx e^{-\infty} = \mathbf{0}$. האלגוריתם מסרב לבצע צעדים רעים, ומתנוון לטיפוס גבעה חמדן רגיל (Greedy Hill-Climbing) ש"נועל" את הפסגה הגבוהה ביותר ומבצע אופטימיזציה מקומית מדויקת.
משפט ההתכנסות: אם קצב ירידת הטמפרטורה איטי דיו (Logarithmic Cooling), מובטח שהאלגוריתם יתכנס לפסגה הגלובלית האופטימלית בהסתברות 1!

💡 2. חיפוש אלומה מקומי (Local Beam Search) ואפקט הגיוס

במקום לנהל מצב בודד, אלגוריתם חיפוש אלומה מחזיק ומנהל בו-זמנית $k$ מצבים נבחרים (ה"אלומה" - Beam).

1. שלב הייצור המשותף (Successor Generation)

בכל איטרציה, האלגוריתם מייצר את כל היורשים האפשריים של כל $k$ המצבים גם יחד לתוך מאגר (Pool) משותף אחד גדול.

2. שלב הבחירה (Selection)

מתוך מאגר כלל היורשים, האלגוריתם בורר את $k$ המצבים הטובים ביותר, והם בלבד מהווים את הדור הבא של האלומה.

ההבדל המהותי בין חיפוש אלומה להרצת $k$ חיפושי טיפוס מקביליים:

בהרצת $k$ חיפושי טיפוס הרים עצמאיים במקביל (Parallel Runs), אין שום שיתוף מידע או תקשורת בין המסלולים. סוכן אחד עשוי להתקדם לעבר אזור צחיח, בעוד שעמיתו מצא מכרה זהב, ואף אחד אינו מסייע לשני.

לעומת זאת, בחיפוש אלומה מתרחש אפקט גיוס משאבים גלובלי (Collective Recruitment): אם אחד מהסוכנים מגלה גבעה פורה ומבטיחה במיוחד, שכניה של אותה גבעה יתפסו את מרבית המקומות ב-$k$ המצבים הנבחרים של הדור הבא! סוכנים שנתקעו באזורים שוממים ננטשים ונמחקים, וכל משאבי החישוב מופנים לסביבה המבטיחה!

⚠️ הסכנה המובנית: אובדן גיוון (Loss of Diversity) והפתרון הסטוכסטי

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

הפתרון: חיפוש אלומה סטוכסטי (Stochastic Beam Search)

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

📊 3. טבלת השוואה כוללת של מטא-היוריסטיקות החיפוש המקומי

אלגוריתם מספר מצבים בזיכרון מנגנון חילוץ ממקסימום מקומי השראה מדעית מגבלה / סיכון מרכזי
טיפוס גבעה (SAHC) 1 אין (נתקע מיד) חמדנות ישירה רגישות מוחלטת למקסימום מקומי ומישורים
חישול מדומה (SA) 1 קבלת צעדים גרועים לפי $P = e^{\Delta E / T}$ פיזיקה סטטיסטית ומטלורגיה קירור מהיר מדי (Quenching) יוביל לתקיעה
חיפוש אלומה (LBS) k שיתוף מידע וגיוס משאבים לאזורים פוריים אינטליגנציית נחיל אובדן גיוון (התכנסות כל ה-$k$ לאותה נקודה)
אלומה סטוכסטית k בחירה הסתברותית משמרת גיוון ברירה טבעית ואבולוציה רעש אקראי עלול לעכב מעט את ההתכנסות

4 5 שאלות המלכודת הקלאסיות במבחן: מקרי קצה אסימפטוטיים באופטימיזציה

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

מלכודת 1: חיפוש אלומה עם $k=1$ LBS ($k=1$)
שקול בדיוק ל: טיפוס גבעה דטרמיניסטי (Hill Climbing)

בכל איטרציה מוחזק מצב בודד ($k=1$), מייצרים את כל שכניו ובוחרים מתוכם את השכן הטוב ביותר בלבד ($k=1$). זוהי בדיוק ההגדרה של טיפוס גבעה חמדני תלול ביותר (Steepest-Ascent Hill Climbing)!

מלכודת 2: חיפוש אלומה עם $k \to \infty$ LBS ($k=\infty$)
שקול בדיוק ל: חיפוש לרוחב (BFS)

כאשר רוחב האלומה $k$ אינו מוגבל (שומרים את כל השכנים שנוצרו ללא קיצוץ), האלגוריתם מפתח את כל המצבים ברמה הנוכחית לפני המעבר לרמה הבאה. זהו למעשה חיפוש לרוחב מלא ללא חסם זיכרון!

מלכודת 3: חישול מדומה עם $T = 0$ SA ($T=0$)
שקול בדיוק ל: First-Choice Hill Climbing

עבור צעד מדרדר ($\Delta E < 0$), הסתברות הקבלה היא $P = e^{\Delta E / T}$. כאשר $T \to 0^+$, החזקה שואפת ל-$-\infty$ ולכן $e^{-\infty} = 0$. צעדים מדרדרים אינם מתקבלים לעולם! צעדים משפרים מתקבלים מיד בהסתברות 1.

מלכודת 4: חישול מדומה עם $T \to \infty$ SA ($T=\infty$)
שקול בדיוק ל: הילוך אקראי טהור (Pure Random Walk)

כאשר הטמפרטורה שואפת לאינסוף ($T \to \infty$), לכל צעד מדרדר מתקיים $\Delta E / T \to 0$, ולכן $P = e^0 = 1$! כל שכן שנבחר אקראית מתקבל בהסתברות ודאית, והאלגוריתם מתעלם לחלוטין מפונקציית המטרה.

מלכודת 5: אלגוריתם גנטי עם גודל אוכלוסייה $N = 1$ GA ($N=1$)
שקול ל: טיפוס הרים סטוכסטי עם מוטציות בלבד (No Crossover)

באלגוריתם גנטי עם פרט בודד ($N=1$), לא ניתן לבצע הכלאה (Crossover) מכיוון שאין הורה שני. הפעולה היחידה שפועלת היא מוטציה על הפרט הבודד, ולכן האלגוריתם הופך לחיפוש מקומי של סוכן יחיד המבוסס על הפרעות אקראיות בלבד.

יחידה 2.7 סיכום מקיף, אינדקס מונחים וגשר לפרק הבא

מילון מושגים וסיכום פרק 2

💡 חיבור כל חלקי הפאזל והכנה מקיפה

כל הכבוד! סיימתם בהצלחה את פרק 2 – אחד הפרקים המרכזיים, המעמיקים והעשירים ביותר בקורס מבוא לבינה מלאכותית. ביחידה מסכמת זו ריכזנו עבורכם מילון מושגים דו-לשוני מקיף עם כל המונחים והנוסחאות שחובה לשלוט בהם, צ'ק-ליסט של נקודות מפתח לבחינה, ואת הגשר הרעיוני אל פרק 3 שבו נצא מסביבות של סוכן יחיד אל עולם המשחקים והחיפוש היריבותי (Minimax וגיזום אלפא-ביתא)!

📖 מילון מושגים אקדמי דו-לשוני (Bilingual Academic Glossary)

היוריסטיקה קבילה (Admissible) Admissible Heuristic

היוריסטיקה שלעולם אינה מעריכה הערכת יתר את עלות ההגעה למטרה: $0 \le h(n) \le h^*(n)$. תנאי הכרחי ומספיק לאופטימליות $A^*$ בחיפוש עץ (Tree Search).

היוריסטיקה עקבית / מונוטונית Consistent / Monotonic

היוריסטיקה המקיימת את אי-שוויון המשולש: $h(n) \le c(n,a,n') + h(n')$. מבטיחה שערכי $f(n)$ מונוטוניים עולים. תנאי הכרחי לאופטימליות $A^*$ בחיפוש גרף (Graph Search).

רפורמולציה (ניסוח מחדש) Representation Reformulation

שינוי בסיס ההצגה של מרחב הבעיה (כגון המרה לבסיס בינארי בבעיית $k \to 2k, 2k+1$) המאפשר פתרון דטרמיניסטי מיידי ב-$O(1)$ ללא כל צורך באלגוריתמי חיפוש.

חיפוש דו-כיווני Bidirectional Search

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

אפקט האדווה (Ripple Effect) Ripple / Side Effects

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

חיפוש מקומי Local Search

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

חישול מדומה Simulated Annealing

מטא-היוריסטיקה בהשראת קירור מתכות. מקבלת צעדים משפרים תמיד, וצעדים מרעים בהסתברות $P = e^{\Delta E / T}$. ככל שהטמפרטורה $T$ יורדת, האלגוריתם מתכנס לחמדן.

חיפוש אלומה מקומי Local Beam Search

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

אובדן גיוון Loss of Diversity

הסכנה שבה כל $k$ סוכני חיפוש האלומה קורסים ומתקבצים כולם סביב אותו מקסימום מקומי. נפתרת באמצעות אלומה סטוכסטית (Stochastic Beam).

רכס (Ridge) Ridge Topography

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

🎯 צ'ק-ליסט: נקודות ברזל שחובה לזכור לבחינה!

✓
קבילות מול עקביות: $Consistent \implies Admissible$. ההפך אינו נכון! קבילות מספיקה ל-Tree Search; עקביות הכרחית ל-Graph Search ללא פתיחה מחדש.
✓
הדוגמה הנגדית של כשל עקביות: בגרף $S \to A \to C \to G$, הקשת $A \to C$ שוברת עקביות כי $h(A) - h(C) = 10 - 5 = 5 > c(A,C) = 1$. צומת $C$ ננעל ב-Closed Set מנתיב נחות, ומונע מ-$A^*$ למצוא את המסלול האופטימלי.
✓
אי-שוויון המשולש: $h(n) \le c(n, a, n') + h(n')$. אם הוא מתקיים, ערכי $f(n)$ מונוטוניים עולים ($f(n') \ge f(n)$).
✓
עץ בינארי $k \to 2k, 2k+1$: אין מעגלים (אין צורך ב-Explored Set). חיפוש לאחור הוא בעל $b=1$ ($Parent = n//2$). ייצוג בינארי משמיט את ה-MSB ונותן פתרון ב-$O(1)$ ללא חיפוש!
✓
לוח $8\times 8$: קיים תמיד מצב מטרה בעומק $\le 32$ (צביעת מיעוט לפי שובך היונים). היוריסטיקת שכנות לקויות אינה קבילה בגלל אפקט האדווה שבו היפוך בודד בעלות 1 פותר מספר שכנות במקביל.
✓
בדיקת קבילות בצמתים ללא מסלול ליעד: אם מצומת אין מסלול ליעד, $h^*(n) = \infty$, ולכן כל ערך היוריסטי סופי הוא קביל אוטומטית!
✓
חישול מדומה: $P = e^{\Delta E / T}$. בטמפרטורה גבוהה מתנהג כהילוך אקראי, בטמפרטורה נמוכה מתכנס לטיפוס גבעה חמדן.
גשר פדגוגי לפרק הבא From Single-Agent to Multi-Agent

הגשר לפרק 3: חיפוש יריבותי, תורת המשחקים ואלגוריתם Minimax

עד עתה, בפרקים 1 ו-2, פעלנו בסביבות של סוכן יחיד (Single-Agent Environment). העולם היה סטטי: הסוכן שקל פעולות, חישב מסלולים וקפץ בין גבעות, מבלי שאיש יפריע לו או ינסה להכשיל את תוכניותיו.

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

בפרק הבא נצלול לתוך חיפוש יריבותי (Adversarial Search): נלמד על עצי משחק, אלגוריתם Minimax ושיקולי עומק, נשלוט בטכניקת גיזום אלפא-ביתא ($\alpha$-$\beta$ Pruning) המכפילה את עומק החיפוש האפקטיבי, ונכיר את "אפקט האופק" (Horizon Effect) ופונקציות הערכה במשחקים!

מעבר לפרק 3: חיפוש מקומי מתקדם ומשחקים יריבותיים
❓

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