algorithm-in-python/math/numericalAnalysis/linear_equation.py

137 lines
3.5 KiB
Python
Raw Normal View History

2018-10-02 21:24:06 +08:00
''' mbinary
#########################################################################
# File : linear_equation.py
# Author: mbinary
# Mail: zhuheqin1@gmail.com
2019-01-31 12:09:46 +08:00
# Blog: https://mbinary.xyz
2018-10-02 21:24:06 +08:00
# Github: https://github.com/mbinary
# Created Time: 2018-10-02 21:14
# Description:
#########################################################################
'''
#coding: utf-8
'''************************************************************************
> File Name: doolittle.py
> Author: mbinary
> Mail: zhuheqin1@gmail.com
2019-01-31 12:09:46 +08:00
> Blog: https://mbinary.xyz
2018-10-02 21:24:06 +08:00
> Created Time: 2018-04-20 08:32
************************************************************************'''
2020-04-15 12:28:20 +08:00
2018-10-02 21:24:06 +08:00
import numpy as np
def getLU(A):
'''doolittle : A = LU,
L is in down-triangle form,
U is in up-triangle form
'''
2020-04-15 12:28:20 +08:00
m, n = A.shape
if m != n:
raise Exception("this matrix is not inversable")
2018-10-02 21:24:06 +08:00
2020-04-15 12:28:20 +08:00
L = np.zeros([m, m])
U = np.zeros([m, m])
2018-10-02 21:24:06 +08:00
L = np.matrix(L)
U = np. matrix(U)
U[0] = A[0]
2020-04-15 12:28:20 +08:00
L[:, 0] = A[:, 0] / A[0, 0]
for i in range(1, m):
for j in range(i, m):
U[i, j] = A[i, j] - sum(L[i, k]*U[k, j] for k in range(i))
L[j, i] = (A[j, i] - sum(L[j, k]*U[k, i]
for k in range(i)))/U[i, i]
2018-10-02 21:24:06 +08:00
print(L)
print(U)
2020-04-15 12:28:20 +08:00
return L, U
2018-10-02 21:24:06 +08:00
def gauss_prior_elimination(A):
'''using guass elimination,get up_trianglge form of A'''
2020-04-15 12:28:20 +08:00
m, n = A.shape
if m != n:
raise Exception("[Error]: matrix is not inversable")
# necessary,otherwise when the dtype of A is int, then it will be wrong
B = np.matrix(A, dtype=float)
for i in range(m-1):
# note using abs value, return a matrix in (m-i)x1 form
col = abs(B[i:, i])
2018-10-02 21:24:06 +08:00
mx = col.max()
2020-04-15 12:28:20 +08:00
if mx == 0:
raise Exception("[Error]: matrix is not inversable")
2018-10-02 21:24:06 +08:00
pos = i+col.argmax()
2020-04-15 12:28:20 +08:00
if pos != i:
B[[pos, i], :] = B[[i, pos], :] # note how to swap cols/rows
B[i, :] = 1/mx*B[i, :]
for j in range(i+1, m):
# print(B)
B[j, :] -= B[j, i] * B[i, :]
2018-10-02 21:24:06 +08:00
print(B)
return B
2020-04-15 12:28:20 +08:00
def solveDown(A, b):
2018-10-02 21:24:06 +08:00
'''A is a matrix in down-triangle form'''
sol = np.zeros(b.shape)
for i in range(b.shape[0]):
2020-04-15 12:28:20 +08:00
sol[i, 0] = (b[i, 0]-sum(A[i, j]*sol[j, 0] for j in range(i)))/A[i, i]
2018-10-02 21:24:06 +08:00
return sol
2020-04-15 12:28:20 +08:00
def solveUp(A, b):
2018-10-02 21:24:06 +08:00
'''A is a matrix in up-triangle form'''
sol = np.zeros(b.shape)
n = b.shape[0]
2020-04-15 12:28:20 +08:00
for i in range(n-1, -1, -1):
sol[i, 0] = (b[i, 0]-sum(A[i, j]*sol[j, 0]
for j in range(n-1, i, -1)))/A[i, i]
2018-10-02 21:24:06 +08:00
return sol
2020-04-15 12:28:20 +08:00
def doolittle(A, b):
L, U = getLU(A)
y = solveDown(L, b)
x = solveUp(U, y)
2018-10-02 21:24:06 +08:00
print(y)
print(x)
return x
2020-04-15 12:28:20 +08:00
def ldlt(A, b):
L, U = getLU(A)
2018-10-02 21:24:06 +08:00
D = np.diag(np.diag(U))
2020-04-15 12:28:20 +08:00
print(D, "D")
z = np.linalg.solve(L, b)
print(z, "z")
y = np.linalg.solve(D, z)
print(y, "y")
x = np.linalg.solve(L.T, y)
print(x, "x")
2018-10-02 21:24:06 +08:00
return x
2020-04-15 12:28:20 +08:00
2018-10-02 21:24:06 +08:00
if __name__ == '__main__':
2020-04-15 12:28:20 +08:00
A = np.matrix([[10, 5, 0, 0],
[2, 2, 1, 0],
[0, 10, 0, 5],
[0, 0, 2, 1]])
b = np.matrix([[5], [3], [27], [6]])
2018-10-02 21:24:06 +08:00
gauss_prior_elimination(A)
'''ldlt
A = np.matrix([[-6,3,2],
[3,5,1],
[2,1,6]])
b = np.matrix([[-4],[11],[-8]])
ldlt(A,b)
'''
'''
A = np.matrix([[2,1,1],
[1,3,2],
[1,2,2]])
b = np.matrix([[4],[6],[5]])
doolittle(A,b)
'''