-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy patheigensolvers.py
72 lines (59 loc) · 1.65 KB
/
eigensolvers.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import numpy as np
import numpy.linalg as la
from epsilon_pseudospectra import mk_A
def power(A, v, tol=1e-10, its=100):
i = 0
v = v/la.norm(v)
while True:
i += 1
v = A.dot(v)
v = v/la.norm(v)
lam = np.dot(v, A.dot(v))
if la.norm(A.dot(v) - lam*v) < tol: break
if i > its:
break
return lam, v
def inverse(A, v, mu=1, tol=1e-10, its=100):
i = 0
v = v/la.norm(v)
I = np.eye(A.shape[0])
while True:
i += 1
v = la.solve(A-mu*I, v)
v = v/la.norm(v)
lam = np.inner(v, A.dot(v))
if la.norm(A.dot(v) - lam*v) < tol: break
if i > its:
break
return lam, v
def rayleigh(A, v, tol=1e-10, its=100):
i = 0
v = v/la.norm(v)
I = np.eye(A.shape[0])
lam = np.dot(v, A.dot(v))
while True:
i += 1
v = la.solve(A-lam*I, v)
v = v/la.norm(v)
lam = np.dot(v, A.dot(v))
error = la.norm(A.dot(v) - lam*v)
if error < tol: break
if i > its:
break
return lam, v
if __name__ == "__main__":
n = 32
A = np.array(mk_A(n))
evals, evecs = la.eigh(A)
v0 = np.random.random(n)
# i = np.argmax(np.abs(evals))
# val, vec = evals[i], evecs[:,i]
print "We apply various algorithms to the matrix of 26.2"
def print_error(lam, v):
print "||Ax-lambda*x|| = {}".format(la.norm(A.dot(v) - lam*v))
print "Power Method with a 1000 iterations"
print_error(*power(A, v0, its=1000))
print "Rayleigh"
print_error(*rayleigh(A, v0))
print "Inverse"
print_error(*inverse(A, v0))