מבני נתונים ואלגוריתמים - מחברת קורס/אלגוריתמים/תכנון דינאמי/תרגילים/זמן הריצה של הכפלת שרשרת מטריצות תחת Memoization/תשובה
א'
[עריכה]נתבונן בפסוודו-קוד עם memoization:
Min-Time(i, j)
1 if M[i][j] != Nil
2 return M[i][j]
3 if i == j
4 M[i][j] = 0
5 return 0
6 min-time = ∞
7 for k in [i, ..., j - 1]
8 guess = Min-Time(i, k) + Min-Time(k + 1, j) + PQR(i, k, j)
9 if guess M[i][j] < min-time
10 M[i][j] = min-time = guess
11 return min-time
נשים לב שאם נניח שכל קריאה רקורסיבית אורכת , אז יש לנו מספר קריאות שכ"א היא
(1-6, 11), ולולאה בת
איטרציות, כאשר כל איטרציה היא . זמן הריצה, לכן הוא
.
ב'
[עריכה]ההוכחה חוזרת, למעשה, על זו של דג הסלמון.
נצייר את עץ הקריאות הרקורסיביות, תוך לקיחה בחשבון את נושא הmemoization.
הציור אינו מראה את כל צמתי הקריאה מטעמי נוחות. הצומת קורא לצומת , בעקיפין לצמתים ו, ולעוד צמתים. הקווים המקווקווים מציינים שהקריאות אינן בהכרח ישירות.
חלק מהצמתים מודגשים, וחלק אינם:
- צומת מודגש אם הוא מתאר קריאה "רצינית", כלומר אחת שבה החלק העיקרי בפונקציה מתבצע (שורות 3-11 ב
Min-Time
). - צומת אינו מודגש אם הוא מתאר קריאה "פושטית", בה לכל היותר רק חלק הmemoization מתבצע (שורות 1-2 ב
Min-Time
).
נשים לב לנקודות הבאות:
- אם צומת לא מודגש, אז אין לו ילדים, ובנוסף, הוא (מדוע?)
- כל צומת מופיע מודגש פעם אחת (מדוע?)
ננתח כעת בשלבים, לפי הרעיון הבא. בכל שלב:
- ניקח צומת מודגש שאין לו ילדים מודגשים.
- ננתח את זמן הריצה שלו, ונרשום את התוצאה בצד. נשים לב שאם לצומת אין ילדים מודגשים, אז כל קריאה רקורסיבית שלו היא אכן (מפני שזו איננה ממש קריאה רקורסיבית). זמן הריצה שלו, לכן, הוא אכן .
- נמיר אותו בצומת לא מודגש, מפני שניתחנו כבר את חלק הקוד המסובך בו (ורשמנו אותו בצד). כל שנותר הוא הקריאה לפונקציה, והיא לוקחת .
נתחיל בצומת המודגש. לצומת זה אין כלל ילדים, ולכן זמן הקריאה הוא בבירור . נרשום בצד שעד כה הקריאות שעברנו עליהן עלו , ונחליף את הצומת בצומת לא מודגש. זה מסמן את העובדה שניתחנו כבר את החלק "עם הבשר" בצומת , וכל שנותר הוא .
נחזור על אותה הפעולה עבור הצומת .
כנ"ל לגבי הצומת .
כעת נתבונן בצומת בשלב בו כל ילדיו אינם מודגשים. כל קריאה רקורסיבית של צומת זה כוללת שני מחירים:
- עצם הקריאה לפונקציה, שעולה
- זמן הקריאה האמיתי, שאותו כבר חייבנו (ורשמנו בצד), ולכן אין צורך לחייב אותו כאן שוב
הפועל היוצא הוא שבשלב זה, מותר לנו לחייב את הצומת אך ורק בקריאות רקורסיביות שעלות כל אחת מהן היא . זה בדיוק .
קל להשתכנע שבשלב בו נחליף את צומת הראש בצומת לא מודגש, רשמנו בצד את כל האיברים מהצורה
,
כאשר
ו. בצורה אחרת, מה שרשום בצד הוא
.
ג'
[עריכה]נשלב את שני הסעיפים הקודמים: .
כבר ראינו כיצד לפשט טור כפול זה בתרגילים בסדרי גדילה.