Direct Solution of Symmetric Systems of Equations¶
The pyma27
Module¶
Ma27: Direct multifrontal solution of symmetric systems.
-
class
hsl.solvers.pyma27.
PyMa27Solver
(A, **kwargs)¶ Bases:
hsl.solvers.sils.Sils
-
fetch_perm
()¶ Return the permutation vector p.
The permutation vector is used to compute the factorization of A. Rows and columns were permuted so that
Pᵀ A P = L B Lᵀwhere i-th row of P is the p(i)-th row of the identity matrix, L is unit upper triangular and B is block diagonal with 1x1 and 2x2 blocks.
-
inertia
¶ Return inertia of matrix A.
Inertia of a matrix is given by (# of λ>0, # of λ<0, # λ=0).
-
refine
(b, nitref=3, tol=1e-08, **kwargs)¶ Perform iterative refinement if necessary.
Iterative refinement is performed until the scaled residual norm ‖b-Ax‖/(1+‖b‖) falls below the threshold ‘tol’ or until nitref steps are taken. Make sure you have called solve() with the same right-hand side b before calling refine(). The residual vector self.residual will be updated to reflect the updated approximate solution.
By default, tol = 1.0e-8 and nitref = 3.
-
solve
(b, get_resid=True)¶ Solve the linear system of equations Ax = b.
The solution will be found in self.x and residual in self.residual.
-
The pyma57
Module¶
Ma57: Direct multifrontal solution of symmetric systems.
-
class
hsl.solvers.pyma57.
PyMa57Solver
(A, factorize=True, **kwargs)¶ Bases:
hsl.solvers.sils.Sils
-
factorize
(A)¶ Perform numerical factorization.
Before this can be done, symbolic factorization (the analyze phase) must have been performed.
The values of the elements of the matrix may have been altered since the analyze phase but the sparsity pattern must not have changed. Use the optional argument newA to specify the updated matrix if applicable.
-
fetch_perm
()¶ Return the permutation vector p.
Permutation vector is used to compute the factorization of A. Rows and columns were permuted so that
Pᵀ A P = L B Lᵀwhere i-th row of P is the p(i)-th row of the identity matrix, L is unit upper triangular and B is block diagonal with 1x1 and 2x2 blocks.
-
inertia
¶ Return inertia of matrix A.
Inertia of a matrix is given by (# of λ>0, # of λ<0, # λ=0).
-
refine
(b, nitref=3, **kwargs)¶ Perform iterative refinement if necessary.
Iterative refinement is performed until the scaled residual norm ‖b-Ax‖/(1+‖b‖) falls below the threshold ‘tol’ or until nitref steps are taken. Make sure you have called solve() with the same right-hand side b before calling refine(). The residual vector self.residual will be updated to reflect the updated approximate solution.
By default, nitref = 3.
-
solve
(b, get_resid=True)¶ Solve the linear system of equations Ax = b.
The solution will be found in self.x and residual in self.residual.
-
Example¶
"""Exemple from MA57 spec sheet: http://www.hsl.rl.ac.uk/specs/ma57.pdf."""
import sys
import numpy as np
from hsl.solvers.src._cyma57_numpy_INT32_FLOAT64 import NumpyMA57Solver_INT32_FLOAT64
n = 5
nnz = 7
A = np.array([[2.0, 3.0, 0, 0, 0], [0, 0, 4.0, 0, 6.0], [0, 0, 1, 5, 0],
[0, 0, 0, 0, 0], [0, 0, 0, 0, 1]], dtype=np.float32)
arow = np.array([0, 0, 1, 1, 2, 2, 4], dtype=np.int32)
acol = np.array([0, 1, 2, 4, 2, 3, 4], dtype=np.int32)
aval = np.array([2.0, 3.0, 4.0, 6.0, 1.0, 5.0, 1.0], dtype=np.float64)
rhs = np.array([8, 45, 31, 15, 17], dtype=np.float64)
context = NumpyMA57Solver_INT32_FLOAT64(n, n, nnz)
context.get_matrix_data(arow, acol, aval)
context.analyze()
context.factorize()
print 'Solve:'
x, residual = context.solve(rhs, True)
# x = context.solve(rhs, False)
print ' x:'
print x
print ' residual:'
print residual
print 'Fetch_perm:'
perm = context.fetch_perm()
print ' perm:'
print perm
print 'Refine:'
(new_x, new_res) = context.refine(x, rhs, residual, 5)
print ' new_x: '
print new_x
print ' new_res: '
print new_res
from cysparse.sparse.ll_mat import *
import cysparse.types.cysparse_types as types
import numpy as np
from hsl.solvers.src._cyma57_cysparse_INT32_FLOAT64 import CySparseMA57Solver_INT32_FLOAT64
import sys
A = LLSparseMatrix(mm_filename=sys.argv[1], itype=types.INT32_T,
dtype=types.FLOAT64_T)
(n, m) = A.shape
e = np.ones(n, 'd')
# rhs = np.zeros(n, 'd')
rhs = A * e
context = CySparseMA57Solver_INT32_FLOAT64(A.nrow, A.ncol, A.nnz)
context.get_matrix_data(A)
context.analyze()
context.factorize()
print 'Fetch_perm:'
perm = context.fetch_perm()
print ' perm:'
print perm
print 'Solve:'
x, residual = context.solve(rhs, True)
print ' x:'
print x
print ' residual:'
print residual
print 'Refine:'
(new_x, new_res) = context.refine(x, rhs, residual, 5)
print ' cond: ', context.cond
print ' new_x: '
print new_x
print ' new_res: '
print new_res
# Demonstrate usage of PyMa27 abstract class for the solution of symmetric
# systems of linear equations.
# Example usage: python demo_ma27.py file1.mtx ... fileN.mtx
# where each fileK.mtx is in MatrixMarket format.
# from hsl.solvers.pyma27 import PyMa27Solver as LBLContext
from hsl.solvers.pyma57 import PyMa57Solver as LBLContext
from pysparse import spmatrix
from numpy.linalg import norm
import timeit
import numpy as np
def Hilbert(n):
"""The cream of ill conditioning: the Hilbert matrix.
See Higham, "Accuracy and Stability of Numerical Algoriths", section 28.1.
The matrix has elements H(i,j) = 1/(i+j-1) when indexed i,j=1..n. However,
here we index as i,j=0..n-1, so the elements are H(i,j) = 1/(i+j+1).
"""
if n <= 0:
return None
if n == 1:
return 1.0
nnz = n * (n - 1) / 2
H = spmatrix.ll_mat_sym(n, nnz)
for i in range(n):
for j in range(i + 1):
H[i, j] = 1.0 / (i + j + 1)
return H
def Ma27SpecSheet():
"""This is the example from the MA27 spec sheet.
Solution should be [1,2,3,4,5]"""
A = spmatrix.ll_mat_sym(5, 7)
A[0, 0] = 2
A[1, 0] = 3
A[2, 1] = 4
A[2, 2] = 1
A[3, 2] = 5
A[4, 1] = 6
A[4, 4] = 1
rhs = np.ones(5, 'd')
rhs[0] = 8
rhs[1] = 45
rhs[2] = 31
rhs[3] = 15
rhs[4] = 17
return (A, rhs)
def solve_system(A, rhs, itref_threshold=1.0e-6, nitrefmax=5, **kwargs):
# Obtain Sils context object
t = timeit.default_timer()
LBL = LBLContext(A, **kwargs)
t_analyze = timeit.default_timer() - t
# Solve system and compute residual
t = timeit.default_timer()
LBL.solve(rhs)
t_solve = timeit.default_timer() - t
# Compute residual norm
nrhsp1 = norm(rhs, ord=np.infty) + 1
nr = norm(LBL.residual) / nrhsp1
# If residual not small, perform iterative refinement
LBL.refine(rhs, tol=itref_threshold, nitref=nitrefmax)
nr1 = norm(LBL.residual, ord=np.infty) / nrhsp1
return (LBL.x, LBL.residual, nr, nr1, t_analyze, t_solve, LBL.neig)
if __name__ == '__main__':
import sys
import os
matrices = sys.argv[1:]
hdr_fmt = '%-13s %-11s %-11s %-11s %-7s %-7s %-5s\n'
res_fmt = '%-13s %-11.5e %-11.5e %-11.5e %-7.3f %-7.3f %-5d\n'
hdrs = ('Name', 'Rel. resid.', 'Residual', 'Resid itref', 'Analyze',
'Solve', 'neig')
header = hdr_fmt % hdrs
lhead = len(header)
sys.stderr.write('-' * lhead + '\n')
sys.stderr.write(header)
sys.stderr.write('-' * lhead + '\n')
# Solve example from the spec sheet
(A, rhs) = Ma27SpecSheet()
(x, r, nr, nr1, t_an, t_sl, neig) = solve_system(A, rhs)
exact = np.arange(5, dtype='d') + 1
relres = norm(x - exact) / norm(exact)
sys.stdout.write(res_fmt %
('Spec sheet', relres, nr, nr1, t_an, t_sl, neig))
# Solve example with Hilbert matrix
n = 10
H = Hilbert(n)
e = np.ones(n, 'd')
rhs = np.empty(n, 'd')
H.matvec(e, rhs)
(x, r, nr, nr1, t_an, t_sl, neig) = solve_system(H, rhs)
relres = norm(x - e) / norm(e)
sys.stdout.write(res_fmt % ('Hilbert', relres, nr, nr1, t_an, t_sl, neig))
# Process matrices given on the command line
for matrix in matrices:
M = spmatrix.ll_mat_from_mtx(matrix)
(m, n) = M.shape
if m != n:
break
e = np.ones(n, 'd')
rhs = np.empty(n, 'd')
M.matvec(e, rhs)
(x, r, nr, nr1, t_an, t_sl, neig) = solve_system(M, rhs)
relres = norm(x - e) / norm(e)
probname = os.path.basename(matrix)
if probname[-4:] == '.mtx':
probname = probname[:-4]
sys.stdout.write(res_fmt %
(probname, relres, nr, nr1, t_an, t_sl, neig))
sys.stderr.write('-' * lhead + '\n')