סעיפים 1.1–1.5
וקטורים, חיבור, כפל בסקלר, מכפלה פנימית וסיבוכיות חישובי וקטורים.
התרגילים מתחילים בעמוד 25 של הספר.
תנאי → זמן לחשוב → רמזים מדורגים → פתרון ברור → בדיקת Python → טעות נפוצה → Take-home message.
תכנון התרגול לפי פרק 1 של Boyd.
וקטורים, חיבור, כפל בסקלר, מכפלה פנימית וסיבוכיות חישובי וקטורים.
התרגילים מתחילים בעמוד 25 של הספר.
הפתרונות אינם נפתחים בעמוד זה, כדי להשאיר את העבודה עצמאית.
שישה תרגילי ליבה ושני תרגילי הרחבה.
לפי מוסכמות הסימון של הספר, קבעו עבור כל משפט אם הוא נכון, לא נכון, או אינו בעל משמעות בגלל סימון לא תקין.
(a) נכון. שני הצדדים הם 3-וקטורים, ובכל מקום מופיע אותו איבר.
(b) סימון לא תקין לפי הספר. הספר אינו משתמש ב-\([1,2,1]\) ככתיבה של וקטור שורה. חשוב לומר שזה כלל סימון של הקורס; בסביבות תכנות סוגריים מרובעים יכולים לייצג רשימה.
(c) נכון. שתי הכתיבות הן אותו וקטור משורשר:
[1, 2, 1] הוא רשימה תקינה, ולכן אסור לערבב בין מוסכמות הספר לבין תחביר Python.נתונים \(a,b\in\mathbb{R}^{10}\) ו-\(c\in\mathbb{R}^{20}\). קבעו אילו ביטויים תקינים, ובמקרה תקין מצאו את האורך.
import numpy as np a = np.zeros(10) b = np.ones(10) c = np.arange(20) print((a + b - c[2:12]).shape) # (10,) print(np.concatenate([a, b, c[2:13]]).shape) # (31,) print(np.concatenate([a, b]).shape) # (20,)
c[2:12].הווקטור \(x\in\mathbb{R}^n\) דליל: רק מעט מאיבריו שונים מאפס. הסבירו במילים מה פירוש הדבר בכל הקשר:
import numpy as np x = np.array([0, 0, 4.2, 0, 0, -1.0, 0]) nnz = np.count_nonzero(x) print(nnz) # 2
הווקטור \(x\) מקודד תנאים באמצעות \(0,1\). אותו מידע מקודד בווקטור \(y\) באמצעות \(-1,+1\).
מצאו נוסחה וקטורית ל-\(y\) באמצעות \(x\), ונוסחה הפוכה ל-\(x\) באמצעות \(y\).
בדיקה רכיבית: אם \(x_i=0\), אז \(y_i=-1\); אם \(x_i=1\), אז \(y_i=1\).
import numpy as np x = np.array([0, 1, 1, 0]) y = 2 * x - 1 x_back = (y + 1) / 2 print(y) # [-1 1 1 -1] print(x_back) # [0. 1. 1. 0.]
חברה מוכרת \(n\) מוצרים. \(p_i\) הוא הרווח ליחידה ממוצר \(i\), ו-\(s_i\) הוא מספר היחידות שנמכרו בתקופה.
הביעו את הרווח הכולל באמצעות \(p\) ו-\(s\).
הערך \(p_i\) נמדד בדולרים ליחידה, \(s_i\) ביחידות, ולכן המכפלה היא בדולרים. החיבור נותן את הרווח הכולל.
import numpy as np p = np.array([4.0, -1.0, 2.5]) s = np.array([100, 10, 40]) total_profit = p @ s print(total_profit) # 490.0
וקטור הציונים \(r\in\mathbb{R}^{10}\) בנוי כך:
הציון הסופי בסולם 0–100 מורכב מ-25% עבודות בית, 35% אמצע ו-40% סופי. מצאו \(w\) כך ש-\(s=w^Tr\).
לכל עבודת בית:
למבחן האמצע:
למבחן הסופי:
לכן:
בדיקת קצה: סטודנט שקיבל את הציון המקסימלי בכל רכיב יקבל \(25+35+40=100\).
import numpy as np
w = np.concatenate([
np.full(8, 25 / 80),
np.array([35 / 120, 40 / 160])
])
max_record = np.array([10] * 8 + [120, 160])
print(w)
print(w @ max_record) # 100.0הווקטור \(x\in\mathbb{R}^{100}\) מתאר התפלגות גילאים: \(x_i\) הוא מספר האנשים בגיל \(i-1\).
הביעו באמצעות סימון וקטורי:
המונה בנוסחת הממוצע הוא סכום הגילאים של כל האנשים, והמכנה הוא מספר האנשים.
import numpy as np x = np.zeros(100, dtype=int) x[20] = 30 # 30 people aged 20 x[70] = 10 # 10 people aged 70 ages = np.arange(100) population = x.sum() over_65 = x[65:].sum() average_age = ages @ x / population print(population, over_65, average_age)
יש לרכוש כמויות \(q\in\mathbb{R}^n\) של \(n\) חומרי גלם. ספק \(k\) מציע וקטור מחירים \(p_k\).
מחיר ההזמנה המלאה אצל ספק \(k\):
בוחרים:
אם מפצלים חצי-חצי בין ספקים \(i,j\), העלות היא:
אבל:
לכן הפיצול אינו יכול להיות זול יותר מן הספק הזול ביותר. ייתכנו יתרונות אחרים, למשל גיבוי או סיכון אספקה, אך לא יתרון מחיר במודל הזה.
import numpy as np
q = np.array([10, 5, 20])
prices = np.array([
[3.0, 4.0, 1.5],
[2.8, 4.5, 1.7],
[3.2, 3.8, 1.6]
])
costs = prices @ q
best = np.argmin(costs)
print(costs)
print(best, costs[best])ארבעה תרגילים מן הספר, ללא פתרונות בעמוד זה.
רעיון מרכזי: stacking ו-slicing
רעיון מרכזי: slicing וחיסור
רעיון מרכזי: וקטור אחדים ומסכה
רעיון מרכזי: אי-שליליות ותמיכות
ארבע שאלות שכדאי לשאול בכל בעיית וקטורים.
ללא משמעות הרכיבים קל לכתוב נוסחה לא נכונה.
בודקים לפני חיבור, חיסור או מכפלה פנימית.
אם כן, חפשו מכפלה פנימית.
מסכה בינארית, דלילות, slicing או stacking יכולים לפשט את הפתרון.