0

I am currently trying to implement some linear algebra functions without numpy.

Given some n by n matrix (stored as lists of lists):

[
 [a, b, c, d],
 [e, f, g, h],
 [i, j, k, l],
 [m, n, o, p]
]

How do I confirm if such matrix is symmetric (the above matrix is equal to the following matrix) without numpy?:

[
 [a, e, i, m],
 [b, f, j, n],
 [c, g, k, o],
 [d, h, l, p]
]

For example,

[
 [1, 2, 3],
 [2, 3, 4],
 [3, 4, 5]
]

and

[
 [1, 7, 3],
 [7, 4, 5],
 [3, 5, 0]
]

are symmetric.

I know the function below works, but this function double counts:

def check_symmetric(array):
  dimensions = len(array)
  for i in range(dimensions):
    for j in range(dimensions):
      if i != j:
        if not(array[i][j] == array[j][i]):
          return False
  return True

Is there a more efficient implementation?

  • 1
    @LarrytheLlama https://en.wikipedia.org/wiki/Symmetric_matrix – no comment Dec 03 '21 at 01:55
  • `list(zip(*array)) == list(zip(*array2[::-1]))[::-1]` - I think I got it for diagonals - it might be the wrong diagonal - let me know EDIT: I added unpacking, but it gives the wrong diagonal. – Larry the Llama Dec 03 '21 at 01:57
  • Larry, you should post an answer. Comments are for questions and clarification. – John Kugelman Dec 03 '21 at 02:24
  • If a matrix is equal to its transpose, then it is symmetric with respect to the main diagonal. – Reti43 Dec 03 '21 at 02:27
  • By the way, if you were to do this manually, like in your attempted method, it suffices to [iterate over the upper triangle indices](https://stackoverflow.com/questions/61872536/traversing-the-upper-triangle-of-a-matrix-in-python) and then check `array[i][j] == array[j][i]`. That way you avoid doing the same checks twice. – Reti43 Dec 03 '21 at 02:33

2 Answers2

0

By definition a matrix is symmetric if it is equal to its transpose.

def transpose(a):
    return [*map(list, zip(*a))]

def is_symmetric(a):
    return transpose(a) == a

print(is_symmetric([[1, 2, 3], [2, 3, 4], [3, 4, 5]])) # True
print(is_symmetric([[1, 2, 3], [4, 5, 6], [7, 8, 9]])) # False
print(is_symmetric([[1, 2, 3], [4, 5, 6]])) # False

Or alternatively, a more direct approach:

def is_symmetric(a):
    if len(a) != len(a[0]): # not even square
        return False
    for i, row in enumerate(a):
        for j, x in enumerate(row[:i]):
            if x != a[j][i]:
                return False
    return True
j1-lee
  • 13,764
  • 3
  • 14
  • 26
0

To make this not do twice the work it needs to

def check_symmetric(array):
  dimensions = len(array)
  for i in range(dimensions):
    for j in range(dimensions):
      if i != j:
        if not(array[i][j] == array[j][i]):
          return False
  return True

make it start at the diagonal.

def check_symmetric(array):
  dimensions = len(array)
  for i in range(dimensions):
    for j in range(i + 1, dimensions):
      if i != j:
        if not(array[i][j] == array[j][i]):
          return False
  return True

Then simplify.

def check_symmetric(array):
  dimensions = len(array)
  for i in range(dimensions):
    for j in range(i + 1, dimensions):
      if array[i][j] != array[j][i]:
        return False
  return True
Ry-
  • 218,210
  • 55
  • 464
  • 476