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
mis not square (the number of rows differs from the length of a row), returnFalse. 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
Trueexactly when every entry is within1e-9of the matching entry of I:abs(entry - target) <= 1e-9, wheretargetis 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