מרחבים ותתי־מרחבים
מרחב העמודות
The Column Space of a Matrix
מגדירים תת־מרחב ו־span, ואז מזהים את C(A)⊆ℝᵐ כאוסף כל היעדים b שעבורם Ax=b פתירה; בסיסו מתקבל מעמודות ה־pivot של A המקורית.
- 1נקודת פתיחהמה כבר ידוע ומה השאלה?
- 2ניבוימה יקרה במקרה הפשוט?
- 3המחשהמה באמת משתנה בתמונה?
- 4ניסוח והצדקהשם, נוסחה ולמה היא נכונה
- 5בדיקהדוגמה, תרגול ומשוב
- 6העברהמקרה חדש והמשך המסלול
שאלה לפני נוסחה
מה אנחנו מנסים לראות?
לבנות מן היסוד את המושגים צירוף לינארי, span ותת־מרחב, ולתרגם את Ax=b לשאלה הגאומטרית אם היעד b נמצא במרחב העמודות של A.
המטריצה A היא מכונה שכל קלט x מתורגם בה לצירוף של עמודותיה. מרחב העמודות הוא כל אזור הפלט שהמכונה מסוגלת להגיע אליו; יעד מחוץ לאזור הזה אינו ניתן לייצור בשום בחירת x.
לפני ההמחשה: קראו רק את הכותרת “האם היעד נוחת על מישור העמודות?”. מה לדעתכם ישתנה, מה יישאר קבוע, ואיזה סימן בתמונה יוכל להפריך את הניבוי?
לראות לפני שמחשבים · המקרה הפשוט ביותר
האם היעד נוחת על מישור העמודות?
שני חצי העמודות a₁,a₂ פורשים את המישור הכחול. היעד b מסומן עליו, ואילו c מסומן מחוץ לו.
מה כדאי לגלות: עקבו מן הראשית אל b: הוא מתקבל מתנועה בשני כיווני העמודות. לעומת זאת ל־c יש רכיב שיוצא מן המישור, ולכן שום בחירת מקדמים לא תגיע אליו.
אחרי שראינו
בסוף השיעור תוכלו
- לבדוק בעזרת שלושת תנאי הסגירות אם קבוצה נתונה היא תת־מרחב.
- לתאר span של וקטורים כאוסף כל הצירופים הלינאריים שלהם.
- לכתוב Ax כצירוף של עמודות A ולהכריע אם b נמצא ב־C(A).
- להשתמש במיקומי pivots כדי לבחור מן העמודות המקוריות רשימה מינימלית שמייצרת את C(A).
נותנים שמות למה שראינו
מושגים שנשתמש בהם
- מרחב וקטורי
- אוסף אובייקטים שאפשר לחבר ולכפול בסקלר תוך שמירה על חוקי החיבור והכפל הרגילים.
- צירוף לינארי
- סכום α₁v₁+⋯+αₖvₖ שבו המקדמים αᵢ הם סקלרים.
- span
- אוסף כל הצירופים הלינאריים של רשימת וקטורים; בעברית: המרחב הנפרש.
- תת־מרחב
- קבוצה בתוך מרחב וקטורי שמכילה את 0 וסגורה לחיבור ולכפל בסקלר.
- מרחב העמודות C(A)
- ה־span של עמודות A; כל הפלטים Ax שהמטריצה מסוגלת לייצר.
- מרחב יעד
- ℝᵐ עבור מטריצה m×n; זהו המרחב שבו חיים Ax והווקטור b.
- עמודת pivot
- עמודה במיקום שבו מתקבל איבר מוביל לאחר אלימינציה; היא מוסיפה כיוון חדש.
- דרגה מספרית
- מספר ה־pivots שהאלגוריתם מזהה ביחס לסף שנבחר; היא עלולה להשתנות כאשר הנתונים כמעט תלויים.
מהמילים אל הסימנים
כותבים את הפעולה שכבר ראינו
פתחו את הנוסחה רק אחרי שאתם יכולים לומר במילים מה כל פעולה אמורה לעשות. בשלב הבא נצדיק אותה צעד אחר צעד.
להצגת נוסחת המפתח
קראו כל סימן כפעולה, לא כמשהו שצריך לשנןC(A)=span{a₁,…,aₙ}⊆ℝᵐמרכיבים את הפעולות
מהתמונה אל הנוסחה — הגזירה, בלי לדלג על הצעדים
מתחילים מצירוף לינארי
המקדמים α ו־β אומרים כמה לנוע בכל כיוון. כאשר נותנים להם לעבור על כל המספרים מתקבל כל האזור שהווקטורים מסוגלים לייצר.
span{u,v}={αu+βv: α,β∈ℝ}עוצרים לחשוב: וקטור יחיד שאינו אפס פורש ישר דרך הראשית; שני וקטורים לא מקבילים ב־ℝ³ פורשים מישור דרך הראשית.
בודקים אם קבוצה היא תת־מרחב
נדרשים שלושה מבחנים: 0 שייך לקבוצה, סכום של שני איברים נשאר בה, וכל כפולה סקלרית נשארת בה. אפשר לאחד את שני תנאי הסגירות ולבדוק αu+βv.
0∈S, u,v∈S ⇒ u+v∈S, αu∈Sעוצרים לחשוב: מישור מוזז כמו z=1 אינו תת־מרחב: הוא אינו מכיל את הראשית.
Span הוא תמיד תת־מרחב
וקטור האפס מתקבל כאשר כל המקדמים אפס. חיבור שני צירופים וכפל צירוף בסקלר רק משנים את המקדמים, ולכן התוצאה עדיין באותו span.
α(Σcᵢvᵢ)+β(Σdᵢvᵢ)=Σ(αcᵢ+βdᵢ)vᵢקוראים את Ax לפי עמודות
אם A היא m×n, כל עמודה aᵢ חיה ב־ℝᵐ וכל קלט x מספק את המקדמים לצירוף שלהן. לכן כל פלט אפשרי שייך ל־span של העמודות.
Ax=x₁a₁+⋯+xₙaₙ, C(A)=span{a₁,…,aₙ}⊆ℝᵐפתירות היא שאלת שייכות
לפתור Ax=b פירושו למצוא מקדמים שמייצרים את b מן העמודות. לכן המערכת פתירה אם ורק אם b נמצא במרחב העמודות.
Ax=b פתירה ⇔ b∈C(A)עוצרים לחשוב: שורה [0 ⋯ 0 | c] עם c≠0 היא דרך אלגברית לראות שהיעד מחוץ למרחב העמודות.
ה־pivots מסירים עמודות מיותרות
RREF מגלה אילו עמודות תלויות בקודמות. את מיקומי ה־pivots קוראים מן המטריצה המצומצמת, אבל את הווקטורים המייצגים לוקחים תמיד מן העמודות המקוריות של A.
pivot indices of RREF(A) → corresponding columns of Aעוצרים לחשוב: לרשימה מינימלית ובלתי מיותרת נקרא בשיעור 5.4 בסיס.
מפרידים בין מתמטיקה מדויקת לחישוב מספרי
במספרים מדויקים pivot הוא אפס או אינו אפס. במחשב שארית זעירה עשויה להיות רעש, ולכן הקוד משתמש בסף יחסי לגודל הנתונים ומדווח דרגה מספרית התלויה בסף.
|pivot|≤τ·scale ⇒ treated as numerical zeroעוצרים לחשוב: סף אינו משנה את הדרגה המתמטית; הוא משנה רק את ההחלטה על נתונים מקורבים.
עכשיו רואים את השיטה בפעולה
דוגמאות פתורות, צעד אחר צעד
תת־מרחב לעומת מישור מוזז
בדקו את S={(x,y,z):z=0} ואת T={(x,y,z):z=1}.
הווקטור 0 נמצא ב־S, כי הרכיב השלישי שלו הוא 0.
אם u₃=v₃=0, אז גם (αu+βv)₃=α·0+β·0=0; לכן S סגורה לצירופים לינאריים.
מכאן S תת־מרחב, ולמעשה S=span{(1,0,0),(0,1,0)}.
לעומת זאת 0 אינו נמצא ב־T כי 0≠1, ולכן T נכשל מיד ואינו תת־מרחב.
מישור דרך הראשית יכול להיות תת־מרחב; אותו מישור לאחר הזזה בדרך כלל אינו תת־מרחב.
S≤ℝ³; T⊆ℝ³, 0∉Tיעד בתוך C(A) ויעד מחוץ לו
עבור A=[[1,2,0],[2,4,1],[3,6,1]], בדקו את b₁=(1,3,4) ואת b₂=(1,0,0).
העמודות הן a₁=(1,2,3), a₂=2a₁ ו־a₃=(0,1,1), ולכן העמודה השנייה אינה מוסיפה כיוון.
b₁=a₁+a₃=(1,3,4), ולכן b₁∈C(A) והמערכת Ax=b₁ פתירה.
אם b₂=αa₁+γa₃, הרכיב הראשון כופה α=1 והרכיב השני כופה γ=−2.
אז הרכיב השלישי היה 3−2=1 ולא 0, ולכן אין מקדמים שמייצרים את b₂.
C(A)=span{a₁,a₃}; היעד הראשון נמצא במישור הזה והשני מחוץ לו.
b₁∈C(A), b₂∉C(A)איפה זה פוגש את העולם
יישום
במערכת הפעלה של שלושה רכיבים, כל עמודה מתארת את תגובת החיישנים להפעלת רכיב אחד. מרחב העמודות אומר אילו פרופילי מדידה אפשר לייצר, והבסיס מגלה אילו מפעילים באמת מוסיפים יכולת חדשה.
מלכודת נפוצה
מה כדאי לבדוק
לחשוב שכל אוסף המכיל את 0 הוא תת־מרחב, או לבחור בסיס ל־C(A) מתוך עמודות המטריצה המצומצמת. RREF מגלה את האינדקסים; את הווקטורים עצמם לוקחים מ־A המקורית.
בודקים שהרעיון יושב
תרגול ומשוב
בדיקת הבנה
בחרו תשובה ורק אז בדקו את עצמכם
בחרו אחת מהאפשרויות כדי להמשיך.
עכשיו אתם
אתגר קצר
דוגמת העוגן לפרק: עבור A=[[2,4,6,4],[2,5,7,6],[2,3,5,2]], השתמשו ב־RREF(A)=[[1,0,1,−2],[0,1,1,2],[0,0,0,0]] כדי לתאר את C(A), למצוא תנאי על b=(b₁,b₂,b₃) לשייכות אליו, ולבדוק את b=(4,3,5) ואת c=(4,3,4).
רמז ראשון
ה־pivots נמצאים בעמודות 1 ו־2, אבל קחו את העמודות האלה מ־A המקורית. וקטור y=(−2,1,1) מאונך לשתיהן.
הצגת דרך הפתרון
- עמודות ה־pivot המקוריות הן a₁=(2,2,2) ו־a₂=(4,5,3), ולכן C(A)=span{a₁,a₂}. העמודות האחרות מיותרות: a₃=a₁+a₂ ו־a₄=−2a₁+2a₂.
- y=(−2,1,1) מאונך ל־a₁ ול־a₂. מאחר שהמישור מממד 2 בתוך ℝ³, הוא בדיוק כל הווקטורים המאונכים ל־y.
- לכן b∈C(A) בדיוק כאשר yᵀb=−2b₁+b₂+b₃=0.
- עבור (4,3,5) מתקבל −8+3+5=0, ואף b=4a₁−a₂. עבור (4,3,4) מתקבל −1, ולכן c∉C(A).
מימוש הנושא
קוד שאפשר לקחת לניסוי
הקוד מיישם את אותו רעיון מתמטי. ב־JavaScript אפשר להריץ אותו כאן; גרסת Python זמינה להשוואה ולהעתקה.
columnSpaceInfo מבצעת RREF, מחזירה את מיקומי ה־pivots ואת העמודות המקוריות המתאימות, ומשווה את הדרגה המספרית של A לזו של [A|b].
עבור b=(4,3,5) תתקבל inColumnSpace=true ועבור c=(4,3,4) false; הדרגה המספרית של A היא 2 ועמודות ה־pivot הן 1 ו־2.
כִּפלו את A ואת b₁ ב־10⁻¹² ובדקו שההכרעה נשמרת. אחר כך שנו את relativeTolerance וצרו עמודה כמעט תלויה כדי לראות שדרגה מספרית תלויה בדיוק המבוקש.
מהרעיון אל הקוד
מימוש חישובי
function rref(input, relativeTolerance=1e-12, scaleColumnCount) {
if (!input.length || !input[0].length) throw new Error("matrix is empty");
const matrix = input.map((row) => row.map(Number));
const rows = matrix.length;
const columns = matrix[0].length;
const referenceColumns = scaleColumnCount ?? columns;
const rowScales = matrix.map((row) =>
Math.max(0, ...row.slice(0, referenceColumns).map(Math.abs)) ||
Math.max(0, ...row.map(Math.abs)),
);
const pivots = [];
let pivotRow = 0;
for (let column = 0; column < columns && pivotRow < rows; column += 1) {
let best = -1;
let bestRatio = 0;
for (let row = pivotRow; row < rows; row += 1) {
const ratio = rowScales[row] === 0
? 0
: Math.abs(matrix[row][column])/rowScales[row];
if (ratio > bestRatio) {
bestRatio = ratio;
best = row;
}
}
if (best === -1 || bestRatio <= relativeTolerance) continue;
[matrix[pivotRow], matrix[best]] = [matrix[best], matrix[pivotRow]];
[rowScales[pivotRow], rowScales[best]] = [rowScales[best], rowScales[pivotRow]];
const scale = matrix[pivotRow][column];
matrix[pivotRow] = matrix[pivotRow].map((value) => value/scale);
for (let row = 0; row < rows; row += 1) {
if (row === pivotRow) continue;
const factor = matrix[row][column];
matrix[row] = matrix[row].map(
(value, j) => value - factor*matrix[pivotRow][j],
);
}
pivots.push(column);
pivotRow += 1;
}
return {
matrix: matrix.map((row) =>
row.map((value) => Math.abs(value) <= relativeTolerance ? 0 : value),
),
pivots,
};
}
function columnSpaceInfo(A, target, relativeTolerance=1e-12) {
const reduced = rref(A, relativeTolerance);
const basis = reduced.pivots.map(
(column) => A.map((row) => row[column]),
);
const augmented = A.map((row, i) => [...row, target[i]]);
const augmentedRank = rref(
augmented,
relativeTolerance,
A[0].length,
).pivots.length;
return {
rank: reduced.pivots.length,
pivotColumns: reduced.pivots.map((index) => index + 1),
basis,
inColumnSpace: augmentedRank === reduced.pivots.length,
};
}
const A = [[2, 4, 6, 4], [2, 5, 7, 6], [2, 3, 5, 2]];
console.log(columnSpaceInfo(A, [4, 3, 5]));
console.log(columnSpaceInfo(A, [4, 3, 4]));def rref(source, relative_tolerance=1e-12, scale_column_count=None):
if not source or not source[0]:
raise ValueError("matrix is empty")
matrix = [[float(value) for value in row] for row in source]
rows, columns = len(matrix), len(matrix[0])
reference_columns = columns if scale_column_count is None else scale_column_count
row_scales = [
max((abs(value) for value in row[:reference_columns]), default=0)
or max((abs(value) for value in row), default=0)
for row in matrix
]
pivots = []
pivot_row = 0
for column in range(columns):
if pivot_row == rows:
break
best = max(
range(pivot_row, rows),
key=lambda row: (
abs(matrix[row][column])/row_scales[row]
if row_scales[row] else 0.0
),
)
best_ratio = (
abs(matrix[best][column])/row_scales[best]
if row_scales[best] else 0.0
)
if best_ratio <= relative_tolerance:
continue
matrix[pivot_row], matrix[best] = matrix[best], matrix[pivot_row]
row_scales[pivot_row], row_scales[best] = (
row_scales[best], row_scales[pivot_row]
)
scale = matrix[pivot_row][column]
matrix[pivot_row] = [value/scale for value in matrix[pivot_row]]
for row in range(rows):
if row == pivot_row:
continue
factor = matrix[row][column]
matrix[row] = [
value - factor*pivot_value
for value, pivot_value
in zip(matrix[row], matrix[pivot_row])
]
pivots.append(column)
pivot_row += 1
matrix = [
[0.0 if abs(value) <= relative_tolerance else value for value in row]
for row in matrix
]
return {"matrix": matrix, "pivots": pivots}
def column_space_info(A, target, relative_tolerance=1e-12):
reduced = rref(A, relative_tolerance)
basis = [
[A[row][column] for row in range(len(A))]
for column in reduced["pivots"]
]
augmented = [row + [target[i]] for i, row in enumerate(A)]
augmented_rank = len(rref(
augmented,
relative_tolerance,
len(A[0]),
)["pivots"])
return {
"rank": len(reduced["pivots"]),
"pivot_columns": [index+1 for index in reduced["pivots"]],
"basis": basis,
"in_column_space": augmented_rank == len(reduced["pivots"]),
}
A = [[2, 4, 6, 4], [2, 5, 7, 6], [2, 3, 5, 2]]
print(column_space_info(A, [4, 3, 5]))
print(column_space_info(A, [4, 3, 4]))לפני שממשיכים
מה לוקחים מהשיעור
- Span הוא כל מה שאפשר לייצר מצירופים לינאריים, והוא תמיד תת־מרחב.
- C(A) הוא אוסף כל הפלטים Ax וחי ב־ℝᵐ כאשר A היא m×n.
- Ax=b פתירה בדיוק כאשר b∈C(A).
- RREF מספק את מיקומי ה־pivots; את עמודות הייצוג לוקחים מ־A המקורית, ובחישוב מספרי מציינים גם את הסף.
משימת מעבדה לשיעור הזה
תחנה 1 — יעד בתוך המרחב או מחוץ לו
הזיזו את b, חזו אם ניתן להרכיב אותו מן העמודות, ורק אחר כך הפעילו את בדיקת השייכות. קשרו בין המיקום החזותי לבין שורת סתירה באלימינציה.
מקורות להעמקה בלבד — השיעור עומד בפני עצמו
מדריך המרצים: עמ׳ 131–135
ספר הלימוד: עמ׳ 251–260