A matrix here is a list of rows (a[i][j] is row i, column j) with complex entries (ints and floats are allowed too). If a has r rows of c entries and b has p rows of q entries, their Kronecker product A \otimes B has r * p rows of c * q entries:
kron_mat(a, b)[i * p + k][j * q + l] = a[i][j] * b[k][l]
for every row i and column j of a and every row k and column l of b. Pictured, it is a grid of blocks: the block in block-row i, block-column j is a[i][j] times the whole matrix b. There is no conjugate, and the order matters. The simulator you are building uses this to turn a gate on one part of a system into a matrix for the whole system.
Write kron_mat(a, b) that returns A \otimes B as a list of rows.
Examples
Input: a = [[0, 1], [1, 0]], b = [[1, 0], [0, 1]]
Output: [[0, 0, 1, 0], [0, 0, 0, 1], [1, 0, 0, 0], [0, 1, 0, 0]]
Explanation: the top-left block is 0 * b, the top-right block is 1 * b, and so on.
The other order, kron_mat(b, a), gives [[0, 1, 0, 0], [1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]].
Input: a = [[1, 2j]], b = [[1], [1j]]
Output: [[1, 2j], [1j, -2]]
Explanation: a has 1 row of 2 entries and b has 2 rows of 1 entry, so the answer has
1 * 2 = 2 rows of 2 * 1 = 2 entries. Its bottom-right entry is a[0][1] * b[1][0] = 2j * 1j = -2.
Constraints
- the answer has at most 64 rows and 64 columns
- answers are compared with a tolerance of
1e-6
Goals
- Build the Kronecker product of two matrices from its index rule
- Read the result as a grid of blocks: each entry of A times the whole of B
- See that A ⊗ B and B ⊗ A are different matrices