You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

180 lines
3.8 KiB

#!/usr/bin/python
# -*- coding: utf-8 -*-
from mpmath import mp
from mpmath import libmp
xrange = libmp.backend.xrange
def run_hessenberg(A, verbose = 0):
if verbose > 1:
print("original matrix (hessenberg):\n", A)
n = A.rows
Q, H = mp.hessenberg(A)
if verbose > 1:
print("Q:\n",Q)
print("H:\n",H)
B = Q * H * Q.transpose_conj()
eps = mp.exp(0.8 * mp.log(mp.eps))
err0 = 0
for x in xrange(n):
for y in xrange(n):
err0 += abs(A[y,x] - B[y,x])
err0 /= n * n
err1 = 0
for x in xrange(n):
for y in xrange(x + 2, n):
err1 += abs(H[y,x])
if verbose > 0:
print("difference (H):", err0, err1)
if verbose > 1:
print("B:\n", B)
assert err0 < eps
assert err1 == 0
def run_schur(A, verbose = 0):
if verbose > 1:
print("original matrix (schur):\n", A)
n = A.rows
Q, R = mp.schur(A)
if verbose > 1:
print("Q:\n", Q)
print("R:\n", R)
B = Q * R * Q.transpose_conj()
C = Q * Q.transpose_conj()
eps = mp.exp(0.8 * mp.log(mp.eps))
err0 = 0
for x in xrange(n):
for y in xrange(n):
err0 += abs(A[y,x] - B[y,x])
err0 /= n * n
err1 = 0
for x in xrange(n):
for y in xrange(n):
if x == y:
C[y,x] -= 1
err1 += abs(C[y,x])
err1 /= n * n
err2 = 0
for x in xrange(n):
for y in xrange(x + 1, n):
err2 += abs(R[y,x])
if verbose > 0:
print("difference (S):", err0, err1, err2)
if verbose > 1:
print("B:\n", B)
assert err0 < eps
assert err1 < eps
assert err2 == 0
def run_eig(A, verbose = 0):
if verbose > 1:
print("original matrix (eig):\n", A)
n = A.rows
E, EL, ER = mp.eig(A, left = True, right = True)
if verbose > 1:
print("E:\n", E)
print("EL:\n", EL)
print("ER:\n", ER)
eps = mp.exp(0.8 * mp.log(mp.eps))
err0 = 0
for i in xrange(n):
B = A * ER[:,i] - E[i] * ER[:,i]
err0 = max(err0, mp.mnorm(B))
B = EL[i,:] * A - EL[i,:] * E[i]
err0 = max(err0, mp.mnorm(B))
err0 /= n * n
if verbose > 0:
print("difference (E):", err0)
assert err0 < eps
#####################
def test_eig_dyn():
v = 0
for i in xrange(5):
n = 1 + int(mp.rand() * 5)
if mp.rand() > 0.5:
# real
A = 2 * mp.randmatrix(n, n) - 1
if mp.rand() > 0.5:
A *= 10
for x in xrange(n):
for y in xrange(n):
A[x,y] = int(A[x,y])
else:
A = (2 * mp.randmatrix(n, n) - 1) + 1j * (2 * mp.randmatrix(n, n) - 1)
if mp.rand() > 0.5:
A *= 10
for x in xrange(n):
for y in xrange(n):
A[x,y] = int(mp.re(A[x,y])) + 1j * int(mp.im(A[x,y]))
run_hessenberg(A, verbose = v)
run_schur(A, verbose = v)
run_eig(A, verbose = v)
def test_eig():
v = 0
AS = []
A = mp.matrix([[2, 1, 0], # jordan block of size 3
[0, 2, 1],
[0, 0, 2]])
AS.append(A)
AS.append(A.transpose())
A = mp.matrix([[2, 0, 0], # jordan block of size 2
[0, 2, 1],
[0, 0, 2]])
AS.append(A)
AS.append(A.transpose())
A = mp.matrix([[2, 0, 1], # jordan block of size 2
[0, 2, 0],
[0, 0, 2]])
AS.append(A)
AS.append(A.transpose())
A= mp.matrix([[0, 0, 1], # cyclic
[1, 0, 0],
[0, 1, 0]])
AS.append(A)
AS.append(A.transpose())
for A in AS:
run_hessenberg(A, verbose = v)
run_schur(A, verbose = v)
run_eig(A, verbose = v)