550 likes | 747 Views
קורס מחשב לרפואנים 274121. הרצאה 9: רקורסיה (המשך). נכתב על-ידי ראובן בר-יהודה. רקורסיה. הגדרה רקורסיבית (מתוך WIKI ) הגדרה היא הגדרה רקורסיבית אם היא מסתמכת על עצמה . דוגמאות:
E N D
קורס מחשב לרפואנים274121 הרצאה 9: רקורסיה (המשך) נכתב על-ידי ראובן בר-יהודה.
רקורסיה • הגדרה רקורסיבית (מתוך 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
מימוש אינדוקטיבי כנגד רקורסיבי כתוב פונקציה שמחשבת סכום של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);
מימוש אינדוקטיבי כנגד רקורסיבי • כתוב פונקציה שמחשבת מכפלתשלn האיברים הראשונים במערך חד מימדי • function y = my_prod(x, n) • y = 1; • for k = 1:n • y = y * x(k); • end • מימוש רקורסיבי • function y = my_prod(x, n) • if n==0y = 1; return;end • y = my_prod(x, n-1) *x(n);
מימוש אינדוקטיבי כנגד רקורסיבי • כתוב פונקציה שמחשבת ORשלn האיברים הראשונים במערך חד מימדי • function y = my_any(x, n) • y = false; • for k = 1:n • y = y || x(k); • end • if y • retuen • end • מימוש רקורסיבי • function y = my_any(x, n) • if n==0y = false; return;end • y = my_any(x, n-1) ||x(n); • if x(n) y=true; return; end • y = my_any(x, n-1) ;
מימוש אינדוקטיבי כנגד רקורסיבי כתוב פונקציה שמחשבת ANDשלn האיברים הראשונים במערך חד מימדי • function y = my_all(x, n) • y = true; • fork = 1:n • y = y && x(n); • end • if ~y • retuen • end • מימוש רקורסיבי • function y = my_all(x, n) • if n==0y = true; return;end • y = my_all(x, n-1) || x(n); • if ~x(n) y=false; return; end • y = my_all(x, n-1) ;
Recursive face Line =2 x=0 y=0 r=100 function [] = face(x,y,r) hold on axis equal cycle(x,y,r); if r < 10 return; end r0 = 0.4*r; face(x-r/2, y+r/3, r0); segment(x,y-r/2,x,y+r/2); face(x+r/2, y+r/3, r0); arc_cycle(x,y,.8*r,1.25*pi,1.75*pi); end
Recursive face Line =3 x=0 y=0 r=100 function [] = face(x,y,r) hold on axis equal cycle(x,y,r); if r < 10 return; end r0 = 0.4*r; face(x-r/2, y+r/3, r0); segment(x,y-r/2,x,y+r/2); face(x+r/2, y+r/3, r0); arc_cycle(x,y,.8*r,1.25*pi,1.75*pi); end
Recursive face Line =4 x=0 y=0 r=100 function [] = face(x,y,r) hold on axis equal cycle(x,y,r); if r < 10 return; end r0 = 0.4*r; face(x-r/2, y+r/3, r0); segment(x,y-r/2,x,y+r/2); face(x+r/2, y+r/3, r0); arc_cycle(x,y,.8*r,1.25*pi,1.75*pi); end
Recursive face Line =5 x=0 y=0 r=100 function [] = face(x,y,r) hold on axis equal cycle(x,y,r); if r < 10 return; end r0 = 0.4*r; face(x-r/2, y+r/3, r0); segment(x,y-r/2,x,y+r/2); face(x+r/2, y+r/3, r0); arc_cycle(x,y,.8*r,1.25*pi,1.75*pi); end
Recursive face Line =8 x=0 y=0 r=100 r0=40 function [] = face(x,y,r) hold on axis equal cycle(x,y,r); if r < 10 return; end r0 = 0.4*r; face(x-r/2, y+r/3, r0); segment(x,y-r/2,x,y+r/2); face(x+r/2, y+r/3, r0); arc_cycle(x,y,.8*r,1.25*pi,1.75*pi); end 40
Recursive face Line =9 x=0 y=0 r=100 r0=40 function [] = face(x,y,r) hold on axis equal cycle(x,y,r); if r < 10 return; end r0 = 0.4*r; face(x-r/2, y+r/3, r0); segment(x,y-r/2,x,y+r/2); face(x+r/2, y+r/3, r0); arc_cycle(x,y,.8*r,1.25*pi,1.75*pi); end -50 +33 40
Recursive face Line =9 x=0 y=0 r=100 r0=40 Line =2 x=-50 y=33 r=40 -50 +33 40 function [] = face(x,y,r) hold on axis equal cycle(x,y,r); if r < 10 return; end r0 = 0.4*r; face(x-r/2, y+r/3, r0); segment(x,y-r/2,x,y+r/2); face(x+r/2, y+r/3, r0); arc_cycle(x,y,.8*r,1.25*pi,1.75*pi); end
Recursive face Line =9 x=0 y=0 r=100 r0=40 Line =3 x=-50 y=33 r=40 function [] = face(x,y,r) hold on axis equal cycle(x,y,r); if r < 10 return; end r0 = 0.4*r; face(x-r/2, y+r/3, r0); segment(x,y-r/2,x,y+r/2); face(x+r/2, y+r/3, r0); arc_cycle(x,y,.8*r,1.25*pi,1.75*pi); end
Recursive face Line =9 x=0 y=0 r=100 r0=40 Line =4 x=-50 y=33 r=40 function [] = face(x,y,r) hold on axis equal cycle(x,y,r); if r < 10 return; end r0 = 0.4*r; face(x-r/2, y+r/3, r0); segment(x,y-r/2,x,y+r/2); face(x+r/2, y+r/3, r0); arc_cycle(x,y,.8*r,1.25*pi,1.75*pi); end
Recursive face Line =9 x=0 y=0 r=100 r0=40 Line =5 x=-50 y=33 r=40 function [] = face(x,y,r) hold on axis equal cycle(x,y,r); if r < 10 return; end r0 = 0.4*r; face(x-r/2, y+r/3, r0); segment(x,y-r/2,x,y+r/2); face(x+r/2, y+r/3, r0); arc_cycle(x,y,.8*r,1.25*pi,1.75*pi); end
Recursive face Line =9 x=0 y=0 r=100 r0=40 Line =8 x=-50 y=33 r=40 function [] = face(x,y,r) hold on axis equal cycle(x,y,r); if r < 10 return; end r0 = 0.4*r; face(x-r/2, y+r/3, r0); segment(x,y-r/2,x,y+r/2); face(x+r/2, y+r/3, r0); arc_cycle(x,y,.8*r,1.25*pi,1.75*pi); end 16
Recursive face Line =9 x=0 y=0 r=100 r0=40 Line =9 x=-50 y=33 r=40 r0=16 function [] = face(x,y,r) hold on axis equal cycle(x,y,r); if r < 10 return; end r0 = 0.4*r; face(x-r/2, y+r/3, r0); segment(x,y-r/2,x,y+r/2); face(x+r/2, y+r/3, r0); arc_cycle(x,y,.8*r,1.25*pi,1.75*pi); end 16 -70 +47 16
Recursive face Line =9 x=0 y=0 r=100 r0=40 Line =8 x=-50 y=33 r=40 r0=16 Line =2 x=-70 y=47 -70 +47 16 function [] = face(x,y,r) hold on axis equal cycle(x,y,r); if r < 10 return; end r0 = 0.4*r; face(x-r/2, y+r/3, r0); segment(x,y-r/2,x,y+r/2); face(x+r/2, y+r/3, r0); arc_cycle(x,y,.8*r,1.25*pi,1.75*pi); end
Recursive face Line =9 x=0 y=0 r=100 r0=40 Line =8 x=-50 y=33 r=40 r0=16 Line =3 x=-70 y=47 function [] = face(x,y,r) hold on axis equal cycle(x,y,r); if r < 10 return; end r0 = 0.4*r; face(x-r/2, y+r/3, r0); segment(x,y-r/2,x,y+r/2); face(x+r/2, y+r/3, r0); arc_cycle(x,y,.8*r,1.25*pi,1.75*pi); end
Recursive face Line =9 x=0 y=0 r=100 r0=40 Line =8 x=-50 y=33 r=40 r0=16 Line =4 x=-70 y=47 function [] = face(x,y,r) hold on axis equal cycle(x,y,r); if r < 10 return; end r0 = 0.4*r; face(x-r/2, y+r/3, r0); segment(x,y-r/2,x,y+r/2); face(x+r/2, y+r/3, r0); arc_cycle(x,y,.8*r,1.25*pi,1.75*pi); end
Recursive face Line =9 x=0 y=0 r=100 r0=40 Line =8 x=-50 y=33 r=40 r0=16 Line =8 x=-70 y=47 function [] = face(x,y,r) hold on axis equal cycle(x,y,r); if r < 10 return; end r0 = 0.4*r; face(x-r/2, y+r/3, r0); segment(x,y-r/2,x,y+r/2); face(x+r/2, y+r/3, r0); arc_cycle(x,y,.8*r,1.25*pi,1.75*pi); end
3D recursive face function [] = face3d(x,y,z,r) hold on axis equal; grid on ellipsoid(x,y,z,r,r,r); if r < 0.1 return; end r0 = 0.3*r; face3d(x-r/2, y+r/3,z+0.9*r, r0); %left recursion face3d(x+r/2, y+r/3,z+0.9*r, r0); %right recursion ellipsoid(x,y,z+r,r/10,r/4,r/2); % nose ellipsoid(x,y-r/2,z+0.8*r,r/2,r/10,r/10); % mouth xlabel('x'); ylabel('y'); zlabel('z'); end
Goole: fractals recursive nature • http://www.google.com/search?hl=en&q=fractals%20recursive%20nature&rlz=1R2SKPB_enIL361&psj=1&bav=on.2,or.r_gc.r_pw.r_qf.,cf.osb&biw=1218&bih=876&wrapid=tlif133698300703510&um=1&ie=UTF-8&tbm=isch&source=og&sa=N&tab=wi&ei=ru-xT9GTOebb4QS55tGNCQ • http://www.youtube.com/watch?NR=1&feature=endscreen&v=-WGRkU2jAFY • http://www.youtube.com/watch?v=ZhtrG6i0cn0 • http://www.youtube.com/watch?v=kt428it7wNc&feature=related • http://www.youtube.com/watch?v=t65lq818c78 • http://www.youtube.com/watch?v=wGdXczRbuKQ&feature=related • http://www.youtube.com/watch?v=P5EkdJRtF-4&feature=related • http://www.youtube.com/watch?v=9oSePXRbW9o&feature=related
משאבי זמן וזיכרון של תוכניות מחשב • אלו מתתי התוכניות הבאות צורכת יותר זמן? הנחה: כל פעולה עולה 1 יחידות זמן. עבור n=0 5 פעולות כל איטרציה מוסיפה 3 פעולות Time(n) = 5 + 5*n עבור n=04 פעולות כל איטרציה מוסיפה 3 פעולות סך מספר האיטרציות הוא n2 Time(n) = 4 + 3*n2 • y =0; • i= 0 + 0 + 0; • while i< n • i=i+1; • y = y +i; • end • i=n*n; • y= 0; • while i>0 • i=i - 1; • end
משאבי זמן וזיכרון של תוכניות מחשב >> n=0:10; >> plot(n,5+5*n,n,4+3*n.^2) >> xlabel('n') >> ylabel('time')
משאבי זמן וזיכרון של תוכניות מחשב אמנם עבור n-ים קטנים הפרבולה מתחת לישר אבל עבור n-ים גדולים הפרבולה גבוהה יותר. מה שמעניין אותנו הם סדרי הגודל: התוכנית הראשונה צורכת זמן בסדר גודל לינארי התוכנית השנייה צורכת זמן בסדר גודל ריבועי ריבועי לינארי שאלה: נניח שעבור n מסויים התוכנית הראשונה תצרוך זמן ריצה של דקה, מה יקרה אם נכפיל את גודלו של nב 1000 ? שאלה: נניח שעבור n מסויים התוכנית השנייה תצרוך זמן ריצה של דקה, מה יקרה אם נכפיל את גודלו של nב 1000 ?
משאבי זמן וזיכרון של תוכניות מחשב (סיבוכיות) דוגמאות לסדרי גודל קבוע: (מסומן ב-(O(1): 1, 10, 123.235, 10001000 לינארי (מסומן ב-(O(n):5 + 5*n, 5n+1999, 0.001n+100000, n+n0.7 ריבועי (מסומן ב-(O(n2):5 + 5*n2, 5n+1999+n2, 0.001n2+100000, 1+2+…+n פולינומי: (מסומן ב poly(n) או (nO(1): 5 + 5*n11, 5n+1999+n12, 0.001n22+100000, לוגריתמי (מסומן ב-((O(log(n):5 + 5*log(n), log(1+2+3+…+n) , log22(n) ובלתי נסבל: אקספוננציאלי: , 1.13n+2 ,2n שאלה: נניח שעבור n מסויים התוכנית האקספוננציאליתתצרוך זמן ריצה של שניה אחת, מה יקרה אם נגדיל את גודלו של nב 100 ? תשובה: 2100 שניות > 1029 שניות > 1026 שעות > 1022שנים
משאבי זמן וזיכרון של תוכניות מחשב (סיבוכיות) דוגמאות לסדרי גודל קבוע: (מסומן ב-(O(1): 1, 10, 123.235, 10001000 לינארי (מסומן ב-(O(n):5 + 5*n, 5n+1999, 0.001n+100000, n+n0.7 ריבועי (מסומן ב-(O(n2):5 + 5*n2, 5n+1999+n2, 0.001n2+100000, 1+2+…+n פולינומי: (מסומן ב poly(n) או (nO(1): 5 + 5*n11, 5n+1999+n12, 0.001n22+100000, לוגריתמי (מסומן ב-((O(log(n):5 + 5*log(n), log(1+2+3+…+n) , log22(n) ובלתי נסבל: אקספוננציאלי: , 1.13n+2 ,2n שאלה: נניח שעבור n מסויים התוכנית הלוגריתמית תצרוך זמן ריצה של דקה אחת, מה יקרה אם נגדיל את גודלו של nפי 101000000 ? תשובה: הזמן הקודם t=log(n) הזמן החדש 107+t >log(n) +log(101000000) =log(101000000n) שזה טיפ טיפה יותר מדקה. כלומר זניח.
משאבי זמן וזיכרון של תוכניות מחשב (סיבוכיות) מה סיבוכיות זמן/זכרון של תתי התוכניות הבאות: a = 1:n; קריאה לפונקציה f(a); קריאה לפונקציה f(a(2:n)) קריאה לפונקציה myfactorial(n)
סיבוכיות החישוב הרקורסיבי של עצרת נספור תחילה כמה פעולות כפל מתבצעות עבור קלט n. • עבור n=1, לא מתבצע כפל. • עבור n=2, מבצעים פעולת כפל אחת. • קל להוכיח באינדוקציה שעבור קלט nמתבצעות בדיוק n-1 פעולות כפל. • מאחר ועל כל פעולת כפל מתבצעות לכל היותר 3 פעולות נוספות, הסיבוכיות היא ליניארית כפונקציה של n. • מה עם סיבוכיותזכרון? תשובה: גם לינארית (בגלל מחסנית הרקורסיה) function f=myfactr(n) if n<2, f=1; else f=n*myfactr(n-1); end
סיבוכיות החישוב של עצרת באלגוריתם לא רקורסיבי גם כאן מספר פעולות כפל המתבצעות עבור קלט n הוא n-1. • במקרה זה לשני המימושים – רקורסיבי ולא רקורסיבי – יש סיבוכיות זמן דומה. ש: מה עם סיבוכיותזכרון? ת: קבוע? לא, כי 2:n דורש זכרוןלינארי נוסף ש: איך אפשר לחסוך זאת? ת: לולאת while functionf=myfactr(n) f=1; for k=2:n f=f*k; end
יחס הזהב, והרמוניות (טבע, ארכיטקטורה, מוזיקה...)
פתרונות רקורסיביים בזבזניים • פתרון רקורסיבי עלול להיות מאד לא יעיל מבחינת סיבוכיות זמן (או מקום). • נדגים זאת על ידי פונקציה רקורסיבית פשוטה לחישוב האבר ה n-י בסדרת פיבונאצ'י. • נעיר שהתכנית הכי יעילה לחישוב האבר ה n-י היא על ידי שימוש בנוסחה הסגורה
rfib: תכנית רקורסיבית לסדרת פיבונאצ'י • להלן פונקציה רקורסיבית לחישוב האבר ה n-י בסדרת פיבונאצ'י על פי ההגדרה. • פונקציה זו מאד לא יעילה: (אקספוננציאלית) function f=rfib(n) if n<=2 f=1; else f=rfib(n-1)+rfib(n-2); end
function f=F(n) if n<=2 f=1; else f=F(n-1)+F(n-2); end F(6) n=6 f = + F(5) F(4) n=5 f = + 3 F(4) F(3) n=4 f = + 2 1 F(3) F(2) n=3 f = + n=2 f = 1 2 F(2) F(1) 1 1 n=1 f = 1 n=2 f = 1
קריאות רקורסיביות של rfib על קלט n=6 function f=rfib(n) if n<=2 f=1; else f=rfib(n-1)+rfib(n-2); end f(6) f(5) f(4) f(4) f(3) f(3) f(2) f(3) f(2) f(2) f(1) f(2) f(1) f(2) f(1)
חישוב סיבוכיותrfib באינדוקציה נגדיר "סיבוכיות זמן" כמספר פעולות ההצבה "f=…" על קלט n. יהי H(n) מספר פעולות ההצבה הנדרשות לביצועrfib(n) . נחשב את H(n) באינדוקציה. בסיס: • חישוב rfib(1) ו-rfib(2) דורש הצבה אחת. כלומר H(1) = H(2) = 1. • חישוב rfib(3): 3 הצבות (חישוב rfib(1) וחישוב rfib(2), וההצבה f=rfib(2)+rfib(1)). function f=rfib(n) if n <= 2 f=1; else f=rfib(n-1)+rfib(n-2); end
שלב מעבר function f=rfib(n) if n <= 2 f=1; else f=rfib(n-1)+rfib(n-2); end חישוב H(n) עבור n>2: • עבורn>2 מתקיים H(n) = H(n-1)+H(n-2)+1 • מכאן ניתן להראות (באינדוקציה) שעבור n>2 מתקיים H(n)>fib(n). • ולכן 5√ = [(1.6180…)n] /( 5/fib(n) > (φnH(n) > כלומר מספר פעולות ההצבה במימוש הרקורסיבי גדל באופן מעריכי (אקספוננציאלי). (להמחשה: fib(10)=55, fib(20)=6765, fib(30) גדול מ 800000, fib(40) גדול מ 100 מיליון... לחישוב rfib(100) יידרשו עשרות אלפי שנים במעבדים המהירים ביותר).
דרך נוספת: H(n) > מספר העלים = fib(n) f(7) function f=rfib(n) if n<=2 f=1; else f=rfib(n-1)+rfib(n-2); end f(6) f(5) f(4) f(4) f(3) f(3) f(2) f(3) f(2) f(2) f(1) f(2) f(1) f(2) f(1)