Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
cantaro86
GitHub Repository: cantaro86/Financial-Models-Numerical-Methods
Path: blob/master/src/FMNM/Solvers.py
1700 views
1
#!/usr/bin/env python3
2
# -*- coding: utf-8 -*-
3
"""
4
Created on Sat Jul 27 11:13:45 2019
5
6
@author: cantaro86
7
"""
8
9
import numpy as np
10
from scipy import sparse
11
from scipy.linalg import norm, solve_triangular
12
from scipy.linalg.lapack import get_lapack_funcs
13
from scipy.linalg.misc import LinAlgError
14
15
16
def Thomas(A, b):
17
"""
18
Solver for the linear equation Ax=b using the Thomas algorithm.
19
It is a wrapper of the LAPACK function dgtsv.
20
"""
21
22
D = A.diagonal(0)
23
L = A.diagonal(-1)
24
U = A.diagonal(1)
25
26
if len(A.shape) != 2 or A.shape[0] != A.shape[1]:
27
raise ValueError("expected square matrix")
28
if A.shape[0] != b.shape[0]:
29
raise ValueError("incompatible dimensions")
30
31
(dgtsv,) = get_lapack_funcs(("gtsv",))
32
du2, d, du, x, info = dgtsv(L, D, U, b)
33
34
if info == 0:
35
return x
36
if info > 0:
37
raise LinAlgError("singular matrix: resolution failed at diagonal %d" % (info - 1))
38
39
40
def SOR(A, b, w=1, eps=1e-10, N_max=100):
41
"""
42
Solver for the linear equation Ax=b using the SOR algorithm.
43
A = L + D + U
44
Arguments:
45
L = Strict Lower triangular matrix
46
D = Diagonal
47
U = Strict Upper triangular matrix
48
w = Relaxation coefficient
49
eps = tollerance
50
N_max = Max number of iterations
51
"""
52
53
x0 = b.copy() # initial guess
54
55
if sparse.issparse(A):
56
D = sparse.diags(A.diagonal()) # diagonal
57
U = sparse.triu(A, k=1) # Strict U
58
L = sparse.tril(A, k=-1) # Strict L
59
DD = (w * L + D).toarray()
60
else:
61
D = np.eye(A.shape[0]) * np.diag(A) # diagonal
62
U = np.triu(A, k=1) # Strict U
63
L = np.tril(A, k=-1) # Strict L
64
DD = w * L + D
65
66
for i in range(1, N_max + 1):
67
x_new = solve_triangular(DD, (w * b - w * U @ x0 - (w - 1) * D @ x0), lower=True)
68
if norm(x_new - x0) < eps:
69
return x_new
70
x0 = x_new
71
if i == N_max:
72
raise ValueError("Fail to converge in {} iterations".format(i))
73
74
75
def SOR2(A, b, w=1, eps=1e-10, N_max=100):
76
"""
77
Solver for the linear equation Ax=b using the SOR algorithm.
78
It uses the coefficients and not the matrix multiplication.
79
"""
80
N = len(b)
81
x0 = np.ones_like(b, dtype=np.float64) # initial guess
82
x_new = np.ones_like(x0) # new solution
83
84
for k in range(1, N_max + 1):
85
for i in range(N):
86
S = 0
87
for j in range(N):
88
if j != i:
89
S += A[i, j] * x_new[j]
90
x_new[i] = (1 - w) * x_new[i] + (w / A[i, i]) * (b[i] - S)
91
92
if norm(x_new - x0) < eps:
93
return x_new
94
x0 = x_new.copy()
95
if k == N_max:
96
print("Fail to converge in {} iterations".format(k))
97
98