Does the Machine Keep Every Length?

matrices · unitary matrices · conjugate transpose · identity matrix · tolerance

A matrix here is a list of rows (m[i][j] is row i, column j) with complex entries (ints and floats allowed too). A square n by n matrix U is unitary when

U^\dagger U = I

where U^\dagger is the conjugate transpose ((U^\dagger)_{ij} = \overline{U_{ji}}, with z.conjugate() for \overline{z}), the product is the usual matrix product (AB)_{ij} = \sum_t A_{it} B_{tj}, and I is the identity matrix (1 on the diagonal, 0 elsewhere). Unitary matrices are exactly the ones that never change the length of a vector, which is why every gate in the simulator you are building will be one.

Write is_unitary(m) that returns True or False:

  • If m is not square (the number of rows differs from the length of a row), return False. This holds even for a tall matrix whose U^\dagger U happens to be an identity matrix: only square matrices count as unitary.
  • Otherwise compute U^\dagger U and return True exactly when every entry is within 1e-9 of the matching entry of I: abs(entry - target) <= 1e-9, where target is 1 on the diagonal and 0 elsewhere.

Examples

Input:  m = [[1, 0], [0, 1j]]
Output: True
Explanation: the dagger is [[1, 0], [0, -1j]], and -1j * 1j = 1. Forgetting the
conjugate would give -1 in the corner.

Input:  m = [[0.6, 0.8j], [0.8j, 0.6]]
Output: True

Input:  m = [[1, 0], [0, 1], [0, 0]]
Output: False
Explanation: three rows of two entries is not square.

Constraints

  • matrices are at most 16 by 16

Goals

  • Test whether a matrix is unitary by checking that its conjugate transpose undoes it
  • Compare floating-point results with a tolerance instead of with ==
  • Rule out non-square matrices before doing any arithmetic
Starting Python…