plshalp
plshalp

Reputation: 565

Checking if a matrix is symmetric in Numpy

I'm trying to make a function with the arguments (a,tol=1e-8) that returns a boolean value that tells the user whether or not the matrix is symmetric (symmetric matrix is equal to its transpose). So far I have:

def check_symmetric(a, tol=1e-8):
if np.transpose(a, axes=axes) == np.transpose(a, axes=axes):
    return True
def sqr(s):
    rows = len(s)
    for row in sq:
        if len(row) != rows:
            return False
    return True
if a != sqr(s):
    raise ValueError

although I keep getting an axes isn't defined message so I'm pretty sure that doesn't work at all...... the tests I'd like to pass are:

e = np.eye(4)
f = np.diag([1], k=3)
g = e[1:, :]

print(check_symmetric(e))
print(not check_symmetric(e + f))
print(check_symmetric(e + f * 1e-9))
print(not check_symmetric(e + f * 1e-9, 1e-10))
try:
    check_symmetric(g)
    print(False)
except ValueError:
    print(True)

Any help is appreciated, thanks!

Upvotes: 50

Views: 88028

Answers (6)

Ma.Te.Pa
Ma.Te.Pa

Reputation: 290

Suppose we were not to consider tolerance e.i. consider integer matrices. We can use .all() in this code to check the corresponding matrix elements and .shape to find matrix dimensions so then we can write something like this:

def check_matrix(A:np.array):
    a, b = A.shape
    if a == b and (-1*np.transpose(A) == A).all():
        return -1
    if a == b and (np.transpose(A) == A).all():
        return 1
    return 0

Takes in a matrix first if statement checks if it's skew symmetrical, second, if it's symmetrical and if neither, returns 0. To adapt this code to floats, use .allclose(). I am aware the previous answer has a better and more concise code but I wanted to share this because answers have not used .shape, so it is unique. :)

Upvotes: 1

Dev-iL
Dev-iL

Reputation: 24169

If using SciPy is acceptable, you can use scipy.linalg.issymmetric() (as of v1.8.0), which also includes some input validation.

  • See implementation here.
  • A note regarding performance (from the docs; emphasis mine):

    When atol and/or rtol are set, then the comparison is performed by numpy.allclose and the tolerance values are passed to it. Otherwise, an exact comparison against zero is performed by internal functions. Hence performance can improve or degrade depending on the size and dtype of the array.

Upvotes: 3

William Dawn
William Dawn

Reputation: 71

This is an old post but I would recommend another method. Especially for sparse matrices, this can be hundreds of times faster.

def is_symmetric(A, tol=1e-8):
    return scipy.sparse.linalg.norm(A-A.T, scipy.Inf) < tol;

Or similar but you get the idea. Using a norm is a much more optimized calculation.

Upvotes: 5

Achintha Ihalage
Achintha Ihalage

Reputation: 2440

If you're not worried about the tot threshold

(a==a.T).all()

is the simplest solution. This works for N-dimensional (N>2) arrays as well.

Upvotes: 8

Andr&#233;s Marulanda
Andr&#233;s Marulanda

Reputation: 448

The following function also solves the problem:

def check_symmetric(a, tol=1e-8):
    return np.all(np.abs(a-a.T) < tol)

Upvotes: 24

Nils Werner
Nils Werner

Reputation: 36765

You can simply compare it to its transpose using allclose

def check_symmetric(a, rtol=1e-05, atol=1e-08):
    return numpy.allclose(a, a.T, rtol=rtol, atol=atol)

Upvotes: 113

Related Questions