960 likes | 1.11k Views
הוראת אינדוקציה ורקורסיה במדעי המחשב. הסמינר המיוחד למורי תיכון מובילים במדעי המחשב טכניון , חיפה, יולי 2012. ראובן בר-יהודה. איך מפולת של אבני דומינו קשור לתכנון לולאות?. תשובה: אינדוקציה. תנאים מספיקים לנפילת שורת אבני הדומינו: בסיס: הראשון נופל. צעד: אם מישהו נופל, אז זה שאחריו נופל.
E N D
הוראת אינדוקציה ורקורסיה במדעי המחשב הסמינר המיוחד למורי תיכון מובילים במדעי המחשב טכניון, חיפה, יולי 2012 ראובן בר-יהודה
איך מפולת של אבני דומינו קשור לתכנון לולאות?
תשובה: אינדוקציה תנאים מספיקים לנפילת שורת אבני הדומינו: בסיס: הראשון נופל. צעד: אם מישהו נופל, אז זה שאחריו נופל OK(1) • OK(n-1) OK(n) ... • OK(n-1) OK(n) OK(1)
תכונות אחרות... תנאים מספיקים לחולי של שורת עכברים: בסיס: הראשון חולה. צעד: אם מישהו חולה, אז זה שאחריו חולה Sick(1) • Sick(n-1)Sick(n) ... • Sick(n-1)Sick(n) Sick(1)
צעדים אחרים מה לגבי צעדי אינדוקציה אחרים, למשל: צעד: המחלה מדבקת בקפיצות של שתיים בסיס: הראשון חולה. • Sick(n-2)Sick(n) Sick(1), Sick(2) ... • Sick(n-2) Sick(n) Sick(1) Sick(2)
אינדוקציה שלמה תנאים מספיקים לנפילת שורת אבני הדומינו: אם כל אלו שלפני נופלים אז גם אני נופל ... ...
אינדוקציה שלמה: דוגמא טענה: דרושים בדיוק n-1 חיתוכים כדי להגיע ל-n קוביות שוקולד. הוכחה: בסיס: n = 1 0 חיתוכים צעד: נחתוך שרירותית לחלקים לא ריקים: n = i + j i < n חיתוכיםi - 1 חיתוכים 1 j < n חיתוכים j - 1 i-1 + j-1 + 1 = n - 1
אינדוקציה לא קווית DOMINOS דוגמאות על הלוח...
תכנון לולאות עם מחשבה באינדוקציה כתוב פונקציה שמחשבת סכום מערך חד מימדי (ללא שימוש בsum ) • function y = my_sum(x) • y = 0; % OK(0) • for n = 1:length(x) % OK(n-1) • y = y + x(n); % OK(n) • end • טענת האינדוקציה. • לאחר nאיטרציות:y = x(1)+x(2)+…+x(n) • הוכחה באינדוקציה על n. • בסיס: 0 =n לאחר 0 איטרציות מכיל את ערך האתחול שהוא 0. • צעד: נניח שלאחר n-1איטרציותy = x(1)+x(2)+…+x(n-1) • באיטרציה ה nמוסיפים לy את x(n) וסיימנו.
תכנון לולאות עם מחשבה באינדוקציה כתוב פונקציה שמחשבת מכפלת מערך חד מימדי (ללא שימוש בprod ) • function y = my_prod(x) • y = 1; % OK(0) • for n = 1:length(x) % OK(n-1) • y = y * x(n); % OK(n) • end • טענת האינדוקציה. • לאחר nאיטרציות:y = x(1)*x(2)*…*x(n) • הוכחה באינדוקציה על n. • בסיס: 0 =n לאחר 0 איטרציות מכיל את ערך האתחול שהוא 1. • צעד: נניח שלאחר n-1איטרציותy = x(1)*x(2)*…*x(n-1) • באיטרציה ה nמכפילים אתy ב x(n) וסיימנו.
תכנון לולאות עם מחשבה באינדוקציה כתוב פונקציה שמחשבת OR של מערך חד מימדי (ללא שימוש בany ) • function y = my_any(x) • y = false; % OK(0) • for n = 1:length(x) % OK(n-1) • y = y || x(n); % OK(n) • end • if y • return • end • טענת האינדוקציה. • לאחר nאיטרציות:y = x(1)x(2)…x(n) • הוכחה באינדוקציה על n. • בסיס: 0 =n לאחר 0 איטרציות מכיל את ערך האתחול שהוא false. • צעד: נניח שלאחר n-1איטרציותy = x(1)x(2)…x(n-1) • באיטרציה ה n"מוסיפים" לy את x(n) וסיימנו.
תכנון לולאות עם מחשבה באינדוקציה כתוב פונקציה שמחשבת AND של מערך חד מימדי (ללא שימוש בall ) • function y = my_all(x) • y = true; % OK(0) • for n = 1:length(x) % OK(n-1) • y = y && x(n); % OK(n) • end • if ~y • return • end • טענת האינדוקציה. • לאחר nאיטרציות:y = x(1)x(2)…x(n) • הוכחה באינדוקציה על n. • בסיס: 0 =n לאחר 0 איטרציות מכיל את ערך האתחול שהוא true. • צעד: נניח שלאחר n-1איטרציותy = x(1)x(2)…x(n-1) • באיטרציה ה n"מכפילים" אתy ב x(n) וסיימנו.
תכנון לולאות עם מחשבה באינדוקציה כתוב פונקציה שמחשבת מקסימום של מערך חד מימדי (ללא שימוש בmax) • function y = my_max(x) • y = -; % OK(0) • for n = 1:length(x) % OK(n-1) • if x(n) > y y = x(n); end % OK(n) • end • טענת האינדוקציה. • לאחר nאיטרציות:y = MAX{x(1),x(2),…,x(n)} • הוכחה באינדוקציה על n. • בסיס: 0 =n לאחר 0 איטרציות מכיל את ערך האתחול שהוא -. • צעד: נניח שלאחר n-1איטרציותy = MAX{x(1),x(2),…,x(n-1)} • באיטרציה ה n"מחליפים, אם גדול יותר" אתy ב x(n) וסיימנו.
תכנון לולאות עם מחשבה באינדוקציה כתוב פונקציה שמחשבת מינימום של מערך חד מימדי (ללא שימוש בmin) • function y = my_min(x) • y = +; % OK(0) • for n = 1:length(x) % OK(n-1) • if x(n) < y y = x(n); end % OK(n) • end • טענת האינדוקציה. • לאחר nאיטרציות:y = MIN{x(1),x(2),…,x(n)} • הוכחה באינדוקציה על n. • בסיס: 0 =n לאחר 0 איטרציות מכיל את ערך האתחול שהוא -. • צעד: נניח שלאחר n-1איטרציותy = MIN{x(1),x(2),…,x(n-1)} • באיטרציה ה n"מחליפים, אם קטן יותר" אתy ב x(n) וסיימנו.
35 12 77 101 5 42 Sorting 1 2 3 4 5 6 101 12 42 35 5 77 1 2 3 4 5 6
sort-by_max.m • function a = sort_by_max( a ) • % sort members of array in non decreasing order • for top = length(a):-1:1 % at this point all members above index “top” are in their proper location • i = index_of_max(a,top); • temp = a(i); a(i) = a(top); a(top) = temp; %swap a(i) with a(top) • end • end • function i_max = index_of_max( a, n ) • % find the index of the maximum member among a(1:n) • i_max = 1; • for i = 2:n % invariant: at this point a(i_max) = MAXIMUM{a(1), a(2)…a(i-1)} • if a(i) > a(i_max) • i_max = i; • end • end • end
חיפוש בינארי • function m = bin_search (x, a) • % a is a non decreasing sorted array • % find x in a and return in m its index. • % if x is not there, m = -1 • b = 1; t = length(a); • while b <= t • m = floor((b+t)/2); • if a(m) == x • return • elseif a(m) > x • t = m-1; • else • b = m+1; • end • end • m = -1;
b t חיפוש בינארי: נכונות שמורות בכל איטרציה x לא נמצא ב a(1 : b-1) x לא נמצא ב a(t+1: end) הוכחה: באינדוקציה על מספר האיטרציות: בסיס: 0 איטרציות- נכונות באופן ריק. צעד: אם a(m) > x אז כל האיברים ב a(m:end) גדולים ממש מ-x ולכן הוא לא שם, אם a(m) < x אז כל האיברים ב a(1:m) קטנים ממש מ-x ולכן הוא לא שם. בסיום: אם x לא נמצא (שורה 5) אז נגיע לשורה 13 בה מתקיים b>t ומכאן נובע שהאיחוד של a(t+1: end) ו a(1 : b-1) מכיל את כל איברי a ולכן, לפי השמורות,x לא נמצא ב-a • function m = bin_search (x, a) • b = 1; t = length(a); • while b <= t • m = floor((b+t)/2); • if a(m) == x • return • elseif a(m) > x • t = m-1; • else • b = m+1; • end • end • m = -1;
חיפוש בינארי: סיבוכיות זמן O(log(n)) • function m = bin_search (x, a) • b = 1; t = length(a); • while b <= t • m = floor((b+t)/2); • if a(m) == x • return • elseif a(m) > x • t = m-1; • else • b = m+1; • end • end • m = -1; בכל איטרציה האינטרוואל b:t נחצה ב-2. אם אורכו בהתחלה היה n אז לאחר איטרציה אחת הוא יהיה בערך n/2 לאחר עוד איטרציה הוא יהיה בערך n/4 לאחר עוד איטרציה הוא יהיה בערך n/8 ולכן לאחר k איטרציות הוא יקטן ל n/2k ש: עבור איזה k הביטוי הנ"ל יהיה קטן מדי? ת: נפתור את אי השוויון: 1 > n/2k או: 2k > n וזה יקרה כאשר k = log2(n) מכאן מספר האיטרציות (ולכן סיבוכיות הזמן) הוא (O(log(n)
Merging two sorted arrays (SilvioMicali MIT) 20 13 7 2 12 11 9 1 … output array
Merging two sorted arrays (SilvioMicali MIT) 20 13 7 2 12 11 9 1 … 1 output array
Merging two sorted arrays (SilvioMicali MIT) 20 13 7 2 12 11 9 1 20 13 7 2 12 11 9 … 1 output array
Merging two sorted arrays (SilvioMicali MIT) 20 13 7 2 12 11 9 1 20 13 7 2 12 11 9 … 1 2 output array
Merging two sorted arrays (SilvioMicali MIT) 20 13 7 2 12 11 9 1 20 13 7 2 12 11 9 20 13 7 12 11 9 … 1 2 output array
Merging two sorted arrays (SilvioMicali MIT) 20 13 7 2 12 11 9 1 20 13 7 2 12 11 9 20 13 7 12 11 9 … 1 2 7 output array
Merging two sorted arrays (SilvioMicali MIT) 20 13 7 2 12 11 9 1 20 13 7 2 12 11 9 20 13 7 12 11 9 20 13 12 11 9 … 1 2 7 output array
Merging two sorted arrays (SilvioMicali MIT) 20 13 7 2 12 11 9 1 20 13 7 2 12 11 9 20 13 7 12 11 9 20 13 12 11 9 … 1 2 7 9 output array
Merging two sorted arrays (SilvioMicali MIT) 20 13 7 2 12 11 9 1 20 13 7 2 12 11 9 20 13 7 12 11 9 20 13 12 11 9 20 13 12 11 … 1 2 7 9 output array
Merging two sorted arrays (SilvioMicali MIT) 20 13 7 2 12 11 9 1 20 13 7 2 12 11 9 20 13 7 12 11 9 20 13 12 11 9 20 13 12 11 … 1 2 7 9 11 output array
Merging two sorted arrays (SilvioMicali MIT) 20 13 7 2 12 11 9 1 20 13 7 2 12 11 9 20 13 7 12 11 9 20 13 12 11 9 20 13 12 11 20 13 12 … 1 2 7 9 11 output array
20 13 7 2 12 11 9 1 20 13 7 2 12 11 9 20 13 7 12 11 9 20 13 12 11 9 20 13 12 11 20 13 12 1 2 7 9 11 12 Merging two sorted arrays (SilvioMicali MIT) … output array
20 13 7 2 12 11 9 1 20 13 7 2 12 11 9 20 13 7 12 11 9 20 13 12 11 9 20 13 12 11 20 13 12 1 2 7 9 11 12 Merging two sorted arrays (SilvioMicali MIT) … output array Time = Q(n) to merge a total of nelements (linear time).
מיזוג • function c = merge(a,b) • % given non decreasing sorted arrays a,b • % return in c the sorted merge of a and b • n_a = length(a); n_b = length(b); • n_c = n_a + n_b; c = zeros(1,n_c); • i_a = 1; i_b = 1; • fori_c = 1 : n_c; • ifi_b > n_b • c(i_c) = a(i_a); • i_a = i_a +1; • elseifi_a > n_a • c(i_c) = b(i_b); • i_b = i_b +1; • elseif a(i_a) < b(i_b) • c(i_c) = a(i_a); • i_a = i_a +1; • else% a(i_a) >= b(i_b) • c(i_c) = b(i_b); • i_b = i_b +1; • end • end
נכונות a(1:i_a)-1 שמורות: c(1:i_c-1)ממויין c(1:i_c-1) מכיל את איברי a(1:i_a-1)b(1:i_b-1) כל האיברים ב c(1:i_c-1) קטנים או שווים לכל האיברים ב a(i_a,end) כל האיברים ב c(1:i_c-1) קטנים או שווים לכל האיברים ב b(i_b,end) באינדוקציה על מספר האיטרציות בסיס: נכון באופן ריק צעד: .. 1 2 3 … i_a n_a
סיבוכיות לינארית ?קבוע • function c = merge(a,b) • % time complexity • % is O(length(a)+length(b)) • n_a = length(a); n_b = length(b); • n_c = n_a + n_b; c = zeros(1,n_c); • i_a = 1; i_b = 1; • fori_c = 1 : n_c; • ifi_b > n_b • c(i_c) = a(i_a); • i_a = i_a +1; • elseifi_a > n_a • c(i_c) = b(i_b); • i_b = i_b +1; • elseif a(i_a) < b(i_b) • c(i_c) = a(i_a); • i_a = i_a +1; • else% a(i_a) >= b(i_b) • c(i_c) = b(i_b); • i_b = i_b +1; • end • end n_a + n_b פעמים קבוע!
רקורסיה • הגדרה היא הגדרה רקורסיבית אם היא מסתמכת על עצמה. דוגמאות: • לפי ההלכה היהודית: "אדם יהודיהוא מי שנולד לאם יהודייה". משמעות ההגדרה הרקורסיבית הינה שעל מנת לדעת אם אדם פלוני, משה, הוא יהודי יש לדעת אם אִמו, דבורה, היא יהודייה. אך בהתאם להגדרה, דבורה יהודייה אם אִמה, רות, היא יהודייה. כדי לבדוק אם רות היא יהודייה צריך להשתמש שוב בהגדרה הרקורסיבית, וכך הלאה. תנאי עצירה יהיה בתחילת קיומו של עמ"י. • הגדרה מילונית־הומוריסטית לערך "רקורסיה": "ראו ערך רקורסיה". • הגדרה רקורסיבית (מתוך WIKI)
אינדוקציה OK(1) בסיס: הראשון נופל. צעד: אם מישהו נופל, אז זה שאחריו נופל • OK(n-1) OK(n) ... • OK(n-1) OK(n) OK(1)
רקורסיה דומינו n מבקש מדומינו n-1 ליפול דומינו n-1מבקש מדומינו n-2 ליפול ... דומינו 2מבקש מדומינו 1 ליפול 1 נופל ורק אז מפולת הדומינו מתחילה האם את יהודיה? האם את יהודיה? האם את יהודיה? האם את יהודיה? האם את יהודיה? ... שרה משה דבורה רות
שימו לב שיש עץ של דומינו שהרקורסיה הנ"ל חשפה בו רק את השרשרת הרלוונטית. משה דבורה רות שרה
רקורסיה בחישוב עצרת function f=myfactr(n) if n==1, f=1; else f=n*myfactr(n-1); end בסיס הרקורסיה קריאה רקורסיבית • נעקב אחרי הביצוע של myfactr(5): n = 5 f= 5 * myfactr(5) n = 4 f= 4 * myfactr(4) n = 3 f= 3 * myfactr(3) n = 2 f= 2 * myfactr(2) n = 1 f= 1 myfactr(1)
רקורסיה בחישוב עצרת • המשך ביצוע: "קפול" הרקורסיה. n = 5 f= 5 * myfactr(5) 120 n = 4 f= 4 * 24 myfactr(4) 6 n = 3 f= 3 * myfactr(3) n = 2 f= 2 * myfactr(2) 2 myfactr(1) n = 1 f= 1 1
הוכחת נכונות שלהפונקציה myfactr • טענה: לכל מספר טבעי n, הפונקציה myfactr עם קלט nעוצרת כאשר הערך של המשתנה f הוא n!. • הוכחת נכונות ע"י אינדוקציה על הקלט n: • בסיס: עבור n<2, בדיקה ישירה מראה כי myfactr(1) תחזיר 1. • צעד: נניח כי myfactr(n-1) = (n-1)!. אזי: myfactr(n) = n∙myfactr(n-1) = n∙(n-1)! = n! function f=myfactr(n) if n<2, f=1; else f=n*myfactr(n-1); end הנחת האינדוקציה
Recursive Mona Liza צייר_מונה(מיקום, גודל) • צייר_מלבן(מיקום, גודל) • אם הגודל קטן מדי, סיים. • צייר_פרצוף(מיקום, גודל) • צייר_מונה (מיקום, גודל מוקטן)
Recursive Mona Liza function [] = mona(x,y,r) hold on plot(x+r*[0 2 2 -2 -2 0], y+r*[0 0 4 4 0 0]) axis equal if r < 0.1 return; end face(x, y+3*r, r) mona(x, y, 0.5*r) end
Face for mona function []=segment(x1,y1,x2,y2) hold on plot([x1,x2],[y1,y2]); end • function [] = face(x,y,r) • cycle(x,y,r); • r0 = 0.3975*r; • cycle(x-r/2, y+r/3, r0); • segment(x,y-r/2,x,y+r/2); • cycle(x+r/2, y+r/3, r0); • arc_cycle(x,y,.8*r,1.25*pi,1.75*pi); • end function []=cycle(x0,y0,r) arc_cycle(x0,y0,r,0,2*pi); end function []=arc_cycle(x0,y0,r,A,B) t = linspace(A,B,100); x = cos(t); y = sin(t); plot(r*x+x0, r*y+y0); end
מימוש אינדוקטיבי כנגד רקורסיבי כתוב פונקציה שמחשבת סכום שלn האיברים הראשונים במערך חד מימדי • function y = my_sum(x, n) • y = 0; • for k = 1:n • y = y + x(k); • end • מימוש רקורסיבי • function y = my_sum(x, n) • if n==0y = 0; return;end • y = my_sum(x, n-1) + x(n);