حل دستگاه معادلات خطی
A·x = b را با تجزیهی LUP و دو جایگذاری حل میکند: اول L·y = P·b رو به جلو، بعد U·x = y رو به عقب؛ با کسرهای دقیق.
با تجزیهی P·A = L·U، معادلهی A·x = b دو معادلهی مثلثی میشود:
- زمان:
O(n³), then O(n²) for each new b - حافظه:
O(n²) - CLRS، بخش ۲۸.۱
A = [[1, 2, 0], [3, 4, 4], [5, 6, 3]] و b = (3, 7, 8)؛ جواب x = (−7/5، 11/5، 3/5).
from fractions import Fractiondef solve(A, b):n = len(A)if len(b) != n:return Nonea = [[Fraction(x) for x in row] for row in A]pi = list(range(n))# 1. P·A = L·U (as on the LUP decomposition page).for k in range(n):p = max(range(k, n), key=lambda i: abs(a[i][k]))if a[p][k] == 0:return Nonepi[k], pi[p] = pi[p], pi[k]a[k], a[p] = a[p], a[k]for i in range(k + 1, n):a[i][k] = a[i][k] / a[k][k]for j in range(k + 1, n):a[i][j] = a[i][j] - a[i][k] * a[k][j]lu = a# 2. Forward substitution: L·y = P·b.y = [Fraction(0)] * nfor i in range(n):y[i] = b[pi[i]][0] - sum(lu[i][j] * y[j] for j in range(i))# 3. Back substitution: U·x = y.x = [Fraction(0)] * nfor i in range(n - 1, -1, -1):x[i] = (y[i] - sum(lu[i][j] * x[j] for j in range(i + 1, n))) / lu[i][i]return [str(v) for v in x]
شروع اجرا
pi—
y—
x—
جدول هنوز خالی است.
متغیرهای محلی
نارنجی = در همین گام عوض شد
A list
[1, 2, 0][3, 4, 4][5, 6, 3]
b list
[3][7][8]
Call stack
- solve()خط 4
گام ۱ از ۶۱
توضیح
ایده
با تجزیهی P·A = L·U، معادلهی A·x = b دو معادلهی مثلثی میشود:
L·y = P·b: چونLپایینمثلثی است،y[0]مستقیم معلوم است، بعدy[1]و … (جایگذاری رو به جلو).U·x = y: چونUبالامثلثی است، از آخرین سطر شروع میکنیم:x[n−1]و بعد بالاتر (جایگذاری رو به عقب).
هزینه
تجزیه O(n³) است، ولی هر جایگذاری فقط O(n²). برای چند b مختلف با همان A، فقط یک بار تجزیه میکنیم. (حساب کردن A⁻¹ و ضرب در b کندتر و از نظر عددی بدتر است.)
در trace به چه چیزی نگاه کنی
- جدول
luهمانLوUدر یک ماتریس است؛ کارتهایyوxبه ترتیب از بالا به پایین و از پایین به بالا پر میشوند.