حل الأنظمة الخطية باستخدام solve()
أوجد حلول أنظمة Ax = b واحسب معكوسات المصفوفات
حل الأنظمة الخطية باستخدام solve() درس مجاني في R Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في R Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة R Academy 4 دروس في المجموع.
الأنظمة الخطية: Ax = b
يمكن كتابة نظام من المعادلات الخطية على الصورة Ax = b، حيث إن A مصفوفة المعاملات، وx متجه المجهولات، وb الطرف الأيمن. ويعني حل x تحليليًا حساب x = A⁻¹b.
# System of equations:
# 2x + y = 5
# x + 3y = 7
# Matrix form: A %*% x = b
A <- matrix(c(2, 1,
1, 3), nrow = 2, byrow = TRUE)
b <- c(5, 7)
# What are A and b?
print(A)
print(b)
cat('We want to find x such that A %*% x = b')solve(A, b): الحل المباشر
تحل solve(A, b) المعادلة Ax = b بالنسبة إلى x. وتستخدم داخليًا تحليل LU، وهو أكثر استقرارًا وكفاءةً عدديًا من حساب A⁻¹ صراحةً ثم ضربها في b.
A <- matrix(c(2, 1,
1, 3), nrow = 2, byrow = TRUE)
b <- c(5, 7)
# Solve Ax = b
x <- solve(A, b)
print(x) # x[1] = ?, x[2] = ?
# Verify: A %*% x should equal b
residual <- A %*% x - b
print(residual) # Should be near zero
# Manual check:
# 2*(8/5) + (9/5) = 16/5 + 9/5 = 25/5 = 5 ✓
# 1*(8/5) + 3*(9/5) = 8/5 + 27/5 = 35/5 = 7 ✓solve(A): معكوس المصفوفة
يعيد استدعاء solve(A) بوسيط واحد فقط معكوس A، أي A⁻¹ الذي يحقق A %*% A⁻¹ = I. تجنّب استخدامه لحل Ax=b؛ واستخدم solve(A,b) مباشرةً، فهو أسرع وأكثر استقرارًا.
A <- matrix(c(4, 3,
3, 2), nrow = 2, byrow = TRUE)
# Compute inverse
A_inv <- solve(A)
print(A_inv)
# Verify: A %*% A_inv = I
A %*% A_inv # Should be identity matrix
round(A %*% A_inv, 10)
# Also A_inv %*% A = I
round(A_inv %*% A, 10)
# det(A) != 0 required for invertibility
det(A) # -1 (nonzero, so invertible)التحقّق من الحل
تحقّق دائمًا من الحل بحساب A %*% x - b. وبسبب الحساب باستخدام الفاصلة العائمة، لن يكون الباقي صفرًا تمامًا، لكنه ينبغي أن يكون قريبًا من إبسيلون الآلة (~1e-15). استخدم norm() للحصول على مقدار واحد للباقي.
A <- matrix(c(3, -1, 2,
1, 4, 0,
-2, 1, 5), nrow = 3, byrow = TRUE)
b <- c(1, 2, 3)
# Solve
x <- solve(A, b)
cat('Solution x:\n'); print(x)
# Residual check
residual <- A %*% x - b
cat('Residual vector:\n'); print(residual)
# Residual norm (should be near 0)
resid_norm <- sqrt(sum(residual^2))
cat('Residual norm:', resid_norm, '\n')
# Expected: something like 2e-16عدد الشرط: kappa()
يقيس عدد الشرط للمصفوفة A مدى حساسية الحل للاضطرابات في b. ويعني عدد الشرط الكبير أن الأخطاء الصغيرة في b قد تسبب أخطاء كبيرة في x؛ أي إن النظام سيئ التكييف.
# Well-conditioned matrix
A_good <- matrix(c(2, 1, 1, 3), nrow = 2, byrow = TRUE)
kappa(A_good) # Small -> good
# Ill-conditioned (nearly singular) matrix
A_bad <- matrix(c(1.000, 1.001,
1.001, 1.002), nrow = 2, byrow = TRUE)
kappa(A_bad) # Very large -> bad!
# Rule of thumb: kappa > 1/machine_epsilon is trouble
.Machine$double.eps # ~2.2e-16
# For A_bad: you lose about log10(kappa) digits of precision
cat('Digits lost:', log10(kappa(A_bad)), '\n')backsolve() للمصفوفات المثلثية العليا
تحل backsolve(R, b) المعادلة Rx = b عندما تكون R مثلثية عُليا، وذلك باستخدام التعويض الخلفي. وهي أسرع بكثير من solve() العام للأنظمة المثلثية: O(n²) مقابل O(n³).
# Upper triangular system: Rx = b
# 2x + 3y + z = 14
# 5y + 2z = 13
# 4z = 8
R <- matrix(c(2, 3, 1,
0, 5, 2,
0, 0, 4), nrow = 3, byrow = TRUE)
b <- c(14, 13, 8)
# Solve using back-substitution
x <- backsolve(R, b)
print(x) # z=2, y=(13-4)/5=9/5, x=(14-3*9/5-2)/2
# Verify
all.equal(as.vector(R %*% x), b) # TRUE
# Compare with general solve
x_general <- solve(R, b)
all.equal(x, x_general) # TRUE (same result)forwardsolve() للمصفوفات المثلثية السفلى
تحل forwardsolve(L, b) المعادلة Lx = b عندما تكون L مثلثية سُفلى، وذلك باستخدام التعويض الأمامي. وهي تكمل backsolve()، وتشكل الدالتان معًا أساس خوارزميات الحل بتحليل LU.
# Lower triangular system: Lx = b
# 3x = 6
# 2x + 4y = 10
# x + 2y + 5z = 16
L <- matrix(c(3, 0, 0,
2, 4, 0,
1, 2, 5), nrow = 3, byrow = TRUE)
b <- c(6, 10, 16)
# Solve using forward-substitution
x <- forwardsolve(L, b)
print(x) # x=2, y=(10-4)/4=1.5, z=(16-2-3)/5=2.2
# Verify
all.equal(as.vector(L %*% x), b) # TRUE
# Use case: solving L*U*x = b
# forwardsolve(L, b) -> y, then backsolve(U, y) -> xأطراف يمنى متعددة
تحل solve(A, B)، حيث إن B مصفوفة، المعادلة AX = B لجميع أعمدة B في الوقت نفسه. وهذا أكثر كفاءةً من استدعاء solve(A, b) على حدة لكل عمود.
A <- matrix(c(2, 1,
1, 3), nrow = 2, byrow = TRUE)
# Solve for two right-hand sides simultaneously
B <- matrix(c(5, 7, # first system
3, 1), # second system
nrow = 2, byrow = TRUE)
# X[:,1] solves Ax = B[:,1]
# X[:,2] solves Ax = B[:,2]
X <- solve(A, B)
print(X)
# Verify both solutions
A %*% X # Should equal B
all.equal(A %*% X, B) # TRUEاكتشاف المصفوفات المفردة
يؤدي استدعاء solve(A) على مصفوفة مفردة إلى ظهور خطأ. تحقّق من det(A) أو rcond(A) (مقلوب عدد الشرط) قبل الحل. واستخدم tryCatch() لكتابة تعليمات برمجية متينة.
# Singular matrix (rows are linearly dependent)
S <- matrix(c(1, 2,
2, 4), nrow = 2, byrow = TRUE)
det(S) # 0 -> singular
kappa(S) # Inf
# Safe solve with tryCatch
safe_solve <- function(A, b) {
tryCatch(
solve(A, b),
error = function(e) {
cat('Matrix is singular or nearly so:\n')
cat(e$message, '\n')
return(NULL)
}
)
}
result <- safe_solve(S, c(1, 2))
print(result) # NULLالمربعات الصغرى باستخدام solve()
في الأنظمة زائدة التحديد (حيث يكون عدد المعادلات أكبر من عدد المجهولات)، لا يوجد حل دقيق. ويقلّل حل المربعات الصغرى من ||Ax - b||² إلى الحد الأدنى. وهو يحل المعادلات الطبيعية: A'Ax = A'b.
# Overdetermined: 4 equations, 2 unknowns (y = a + b*x)
set.seed(1)
x_vals <- c(1, 2, 3, 4)
y_vals <- c(2.1, 4.0, 5.9, 8.2) # approx y = 0 + 2x
A <- cbind(1, x_vals) # Design matrix (4x2)
b <- y_vals
# Normal equations: (A'A) beta = A'b
AtA <- crossprod(A)
Atb <- crossprod(A, b)
beta_ols <- solve(AtA, Atb)
print(beta_ols) # Intercept ~0.1, slope ~2.0
# Residual sum of squares
y_hat <- A %*% beta_ols
rss <- sum((b - y_hat)^2)
cat('RSS:', rss)استخدام qr.solve() لتحقيق الاستقرار
تُعد qr.solve(A, b) أكثر استقرارًا عدديًا من solve() للأنظمة سيئة التكييف أو زائدة التحديد. فهي تستخدم تحليل QR بدلًا من LU. وتستخدم lm() هذه الطريقة داخليًا.
# For overdetermined system, qr.solve is preferred
x_vals <- c(1, 2, 3, 4, 5)
y_vals <- c(1.9, 4.1, 6.0, 7.8, 10.1)
A <- cbind(1, x_vals)
b <- y_vals
# qr.solve handles overdetermined systems directly
beta_qr <- qr.solve(A, b)
print(beta_qr) # intercept, slope
# Equivalent to:
beta_lm <- coef(lm(y_vals ~ x_vals))
all.equal(beta_qr, beta_lm, check.names = FALSE) # TRUE
# For well-determined square systems, solve() is fine
# For overdetermined or ill-conditioned: use qr.solve()تحقّق سريع
اختبر مدى فهمك لحل الأنظمة الخطية في R.
مراجعة: حل الأنظمة الخطية
أهم النقاط: تحل solve(A, b) المعادلة Ax=b مباشرةً، وهي الطريقة المفضلة. تحسب solve(A) المعكوس A⁻¹، لذا تجنّبها عند الحل. تكون backsolve(R,b) وforwardsolve(L,b) سريعتين للأنظمة المثلثية. يقيس kappa(A) حالة التكييف؛ وتعني القيم الكبيرة حلولًا غير مستقرة. استخدم qr.solve() للأنظمة زائدة التحديد. وتحقّق دائمًا باستخدام A %*% x - b.
# Summary of solve() functions:
A <- matrix(c(3, 1, 1, 2), nrow = 2)
b <- c(9, 8)
# Solve Ax = b
x <- solve(A, b)
print(x) # c(2, 3)
# Check conditioning
kappa(A) # Small -> well-conditioned
# Verify
max(abs(A %*% x - b)) # Near zero
# For triangular systems:
R <- matrix(c(2, 3, 0, 4), nrow = 2, byrow = TRUE)
backsolve(R, c(8, 4)) # x=c(1, 1)
# For least squares (overdetermined):
# qr.solve(design_matrix, y)الأسئلة الشائعة
هل درس «حل الأنظمة الخطية باستخدام solve()» مجاني؟
نعم — نص درس «حل الأنظمة الخطية باستخدام solve()» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة R Academy، انتقل إلى CoddyKit PRO. تتضمن دورة R Academy 4 دروس في المجموع.
ماذا ستتعلم في «حل الأنظمة الخطية باستخدام solve()»؟
أوجد حلول أنظمة Ax = b واحسب معكوسات المصفوفات تتمرن على R Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ R Academy؟
لا تُشترط خبرة سابقة. R Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.
كم من الوقت يستغرق درس «حل الأنظمة الخطية باستخدام solve()»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس R Academy هذا؟
نعم. كل درس في R Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- ضرب المصفوفات والمحددات
- حل الأنظمة الخطية باستخدام solve()
- القيم الذاتية والمتجهات الذاتية
- تحليلات SVD وQR وتشولسكي