def test_real_numbers(self): for m, n in self.test_dimensions: # Obtain a random real matrix of orthonormal rows Q = random_unitary_matrix(n, real=True) Q = Q[:m, :] # Get Givens decomposition of Q givens_rotations, V, diagonal = givens_decomposition(Q) # Compute U U = numpy.eye(n, dtype=complex) for parallel_set in givens_rotations: combined_givens = numpy.eye(n, dtype=complex) for i, j, theta, phi in reversed(parallel_set): c = numpy.cos(theta) s = numpy.sin(theta) phase = numpy.exp(1.j * phi) G = numpy.array([[c, -phase * s], [s, phase * c]], dtype=complex) givens_rotate(combined_givens, G, i, j) U = combined_givens.dot(U) # Compute V * Q * U^\dagger W = V.dot(Q.dot(U.T.conj())) # Construct the diagonal matrix D = numpy.zeros((m, n), dtype=complex) D[numpy.diag_indices(m)] = diagonal # Assert that W and D are the same for i in range(m): for j in range(n): self.assertAlmostEqual(D[i, j], W[i, j])
def test_4_by_9(self): m, n = (4, 9) # Obtain a random matrix of orthonormal rows x = numpy.random.randn(n, n) y = numpy.random.randn(n, n) A = x + 1.j * y Q, R = qr(A) Q = Q[:m, :] # Get Givens decomposition of Q V, givens_rotations, diagonal = givens_decomposition(Q) # Compute U U = numpy.eye(n, dtype=complex) for parallel_set in givens_rotations: combined_givens = numpy.eye(n, dtype=complex) for i, j, theta, phi in parallel_set: c = numpy.cos(theta) s = numpy.sin(theta) phase = numpy.exp(1.j * phi) G = numpy.array([[c, -phase * s], [s, phase * c]], dtype=complex) givens_rotate(combined_givens, G, i, j) U = combined_givens.dot(U) # Compute V * Q * U^\dagger W = V.dot(Q.dot(U.T.conj())) # Construct the diagonal matrix D = numpy.zeros((m, n), dtype=complex) D[numpy.diag_indices(m)] = diagonal # Assert that W and D are the same for i in range(m): for j in range(n): self.assertAlmostEqual(D[i, j], W[i, j])
def test_bad_input(self): """Test bad input.""" with self.assertRaises(ValueError): v = numpy.random.randn(2) G = givens_matrix_elements(v[0], v[1]) givens_rotate(v, G, 0, 1, which='a')
def test_main_procedure(self): for n in self.test_dimensions: # Obtain a random quadratic Hamiltonian quadratic_hamiltonian = random_quadratic_hamiltonian(n) # Get the diagonalizing fermionic unitary ferm_unitary = ( quadratic_hamiltonian.diagonalizing_bogoliubov_transform()) lower_unitary = ferm_unitary[n:] # Get fermionic Gaussian decomposition of lower_unitary decomposition, left_decomposition, diagonal, left_diagonal = ( fermionic_gaussian_decomposition(lower_unitary)) # Compute left_unitary left_unitary = numpy.eye(n, dtype=complex) for parallel_set in left_decomposition: combined_op = numpy.eye(n, dtype=complex) for op in reversed(parallel_set): i, j, theta, phi = op c = numpy.cos(theta) s = numpy.sin(theta) phase = numpy.exp(1.j * phi) givens_rotation = numpy.array( [[c, -phase * s], [s, phase * c]], dtype=complex) givens_rotate(combined_op, givens_rotation, i, j) left_unitary = combined_op.dot(left_unitary) for i in range(n): left_unitary[i] *= left_diagonal[i] left_unitary = left_unitary.T for i in range(n): left_unitary[i] *= diagonal[i] # Check that left_unitary zeroes out the correct entries of # lower_unitary product = left_unitary.dot(lower_unitary) for i in range(n - 1): for j in range(n - 1 - i): self.assertAlmostEqual(product[i, j], 0.) # Compute right_unitary right_unitary = numpy.eye(2 * n, dtype=complex) for parallel_set in decomposition: combined_op = numpy.eye(2 * n, dtype=complex) for op in reversed(parallel_set): if op == 'pht': swap_rows(combined_op, n - 1, 2 * n - 1) else: i, j, theta, phi = op c = numpy.cos(theta) s = numpy.sin(theta) phase = numpy.exp(1.j * phi) givens_rotation = numpy.array( [[c, -phase * s], [s, phase * c]], dtype=complex) double_givens_rotate(combined_op, givens_rotation, i, j) right_unitary = combined_op.dot(right_unitary) # Compute left_unitary * lower_unitary * right_unitary^\dagger product = left_unitary.dot( lower_unitary.dot(right_unitary.T.conj())) # Construct the diagonal matrix diag = numpy.zeros((n, 2 * n), dtype=complex) diag[range(n), range(n, 2 * n)] = diagonal # Assert that W and D are the same for i in numpy.ndindex((n, 2 * n)): self.assertAlmostEqual(diag[i], product[i])