import numpy as np
def forward_sub(L, b):
"""Given a lower triangular matrix L and right-side vector b,
compute the solution vector y solving Ly = b."""
y = np.zeros_like(b)
for i in range(len(b)):
s = np.dot(L[i, :i], y[:i])
y[i] = b[i] - s
return y
def backward_sub(U, y):
"""Given a lower triangular matrix U and right-side vector y,
compute the solution vector x solving Ux = y."""
x = np.zeros_like(y)
for i in range(len(x), 0, -1):
x[i-1] = (y[i-1] - np.dot(U[i-1, i:], x[i:])) / U[i-1, i-1]
return x
def lu_factor(A):
#LU decompostion using Doolittles method
L = np.zeros_like(A)
U = np.zeros_like(A)
N = np.size(A,0)
"""for i in range(N):
for k in range(i, N):
U[i,k] = A[i,k] - np.dot(L[i, :i], U[:i, k])
L[i,i] = 1
for k in range(i+1, N):
L[k,i] = (A[k,i] - np.dot(L[k, :i], U[:i, i])) / U[i,i]"""
for k in range(N):
L[k, k] = 1
U[k, k] = (A[k, k] - np.dot(L[k, :k], U[:k, k]))
for j in range(k+1, N):
U[k, j] = (A[k, j] - np.dot(L[k, :k], U[:k, j]))
for i in range(k+1, N):
L[i, k] = (A[i, k] - np.dot(L[i, :k], U[:k, k])) / U[k, k]
return (L, U)
def lu_solve(L, U, b):
# Step 1: Solve Uy = b using forward substitution
# Step 2: Solve Lx = y using backward substitution
y = forward_sub(L,b)
x = backward_sub(U,y)
return x
def linear_solve(A, b):
# ...
L, U = lu_factor(A)
print(L)
print(U)
print(L @ U)
x = lu_solve(L,U,b)
return x
b = np.array([6.0,-4,27])
A = np.matrix([[1.,1,1],
[0,2,5],
[2,5,-1]])
print(linear_solve(A,b))
aW1wb3J0IG51bXB5IGFzIG5wCgpkZWYgZm9yd2FyZF9zdWIoTCwgYik6CiAgICAiIiJHaXZlbiBhIGxvd2VyIHRyaWFuZ3VsYXIgbWF0cml4IEwgYW5kIHJpZ2h0LXNpZGUgdmVjdG9yIGIsCiAgICBjb21wdXRlIHRoZSBzb2x1dGlvbiB2ZWN0b3IgeSBzb2x2aW5nIEx5ID0gYi4iIiIKCiAgICB5ID0gbnAuemVyb3NfbGlrZShiKQogICAgZm9yIGkgaW4gcmFuZ2UobGVuKGIpKToKICAgICAgcyA9IG5wLmRvdChMW2ksIDppXSwgeVs6aV0pCiAgICAgIHlbaV0gPSBiW2ldIC0gcwogICAgcmV0dXJuIHkKCmRlZiBiYWNrd2FyZF9zdWIoVSwgeSk6CiAgICAiIiJHaXZlbiBhIGxvd2VyIHRyaWFuZ3VsYXIgbWF0cml4IFUgYW5kIHJpZ2h0LXNpZGUgdmVjdG9yIHksCiAgICBjb21wdXRlIHRoZSBzb2x1dGlvbiB2ZWN0b3IgeCBzb2x2aW5nIFV4ID0geS4iIiIKCiAgICB4ID0gbnAuemVyb3NfbGlrZSh5KQoKICAgIGZvciBpIGluIHJhbmdlKGxlbih4KSwgMCwgLTEpOgogICAgICB4W2ktMV0gPSAoeVtpLTFdIC0gbnAuZG90KFVbaS0xLCBpOl0sIHhbaTpdKSkgLyBVW2ktMSwgaS0xXQoKICAgIHJldHVybiB4CgpkZWYgbHVfZmFjdG9yKEEpOgoKICAjTFUgZGVjb21wb3N0aW9uIHVzaW5nIERvb2xpdHRsZXMgbWV0aG9kCgogIEwgPSBucC56ZXJvc19saWtlKEEpCiAgVSA9IG5wLnplcm9zX2xpa2UoQSkKCiAgTiA9IG5wLnNpemUoQSwwKQoKICAiIiJmb3IgaSBpbiByYW5nZShOKToKICAgIGZvciBrIGluIHJhbmdlKGksIE4pOgogICAgICBVW2ksa10gPSBBW2ksa10gLSBucC5kb3QoTFtpLCA6aV0sIFVbOmksIGtdKQogICAgTFtpLGldID0gMQogICAgZm9yIGsgaW4gcmFuZ2UoaSsxLCBOKToKICAgICAgTFtrLGldID0gKEFbayxpXSAtIG5wLmRvdChMW2ssIDppXSwgVVs6aSwgaV0pKSAvIFVbaSxpXSIiIgogIGZvciBrIGluIHJhbmdlKE4pOgogICAgTFtrLCBrXSA9IDEKICAgIFVbaywga10gPSAoQVtrLCBrXSAtIG5wLmRvdChMW2ssIDprXSwgVVs6aywga10pKQogICAgZm9yIGogaW4gcmFuZ2UoaysxLCBOKToKICAgICAgVVtrLCBqXSA9IChBW2ssIGpdIC0gbnAuZG90KExbaywgOmtdLCBVWzprLCBqXSkpCiAgICBmb3IgaSBpbiByYW5nZShrKzEsIE4pOgogICAgICBMW2ksIGtdID0gKEFbaSwga10gLSBucC5kb3QoTFtpLCA6a10sIFVbOmssIGtdKSkgLyBVW2ssIGtdCiAgcmV0dXJuIChMLCBVKQoKCmRlZiBsdV9zb2x2ZShMLCBVLCBiKToKICAgICMgU3RlcCAxOiBTb2x2ZSBVeSA9IGIgdXNpbmcgZm9yd2FyZCBzdWJzdGl0dXRpb24KCiAgICAjIFN0ZXAgMjogU29sdmUgTHggPSB5IHVzaW5nIGJhY2t3YXJkIHN1YnN0aXR1dGlvbgoKICAgIHkgPSBmb3J3YXJkX3N1YihMLGIpCiAgICB4ID0gYmFja3dhcmRfc3ViKFUseSkKCiAgICByZXR1cm4geAoKCmRlZiBsaW5lYXJfc29sdmUoQSwgYik6CiAgICAjIC4uLgoKICAgIEwsIFUgPSBsdV9mYWN0b3IoQSkKICAgIHByaW50KEwpCiAgICBwcmludChVKQogICAgcHJpbnQoTCBAIFUpCiAgICB4ID0gbHVfc29sdmUoTCxVLGIpCiAgICByZXR1cm4geAoKCmIgPSBucC5hcnJheShbNi4wLC00LDI3XSkKQSA9IG5wLm1hdHJpeChbWzEuLDEsMV0sCiAgICAgICAgICAgICAgIFswLDIsNV0sCiAgICAgICAgICAgICAgIFsyLDUsLTFdXSkKCnByaW50KGxpbmVhcl9zb2x2ZShBLGIpKQo=