def test_diagonalizing_bogoliubov_transform(self): """Test diagonalizing Bogoliubov transform.""" hermitian_part = numpy.array( [[0.0, 1.0, 0.0], [1.0, 0.0, 1.0], [0.0, 1.0, 0.0]], dtype=complex) antisymmetric_part = numpy.array( [[0.0, 1.0j, 0.0], [-1.0j, 0.0, 1.0j], [0.0, -1.0j, 0.0]], dtype=complex) quad_ham = QuadraticHamiltonian(hermitian_part, antisymmetric_part) block_matrix = numpy.zeros((6, 6), dtype=complex) block_matrix[:3, :3] = antisymmetric_part block_matrix[:3, 3:] = hermitian_part block_matrix[3:, :3] = -hermitian_part.conj() block_matrix[3:, 3:] = -antisymmetric_part.conj() _, transformation_matrix, _ = ( quad_ham.diagonalizing_bogoliubov_transform()) left_block = transformation_matrix[:, :3] right_block = transformation_matrix[:, 3:] ferm_unitary = numpy.zeros((6, 6), dtype=complex) ferm_unitary[:3, :3] = left_block ferm_unitary[:3, 3:] = right_block ferm_unitary[3:, :3] = numpy.conjugate(right_block) ferm_unitary[3:, 3:] = numpy.conjugate(left_block) # Check that the transformation is diagonalizing majorana_matrix, _ = quad_ham.majorana_form() canonical, _ = antisymmetric_canonical_form(majorana_matrix) diagonalized = ferm_unitary.conj().dot( block_matrix.dot(ferm_unitary.T.conj())) for i in numpy.ndindex((6, 6)): self.assertAlmostEqual(diagonalized[i], canonical[i])
def test_equality(self): """Test that the decomposition is valid.""" n = 7 antisymmetric_matrix = random_antisymmetric_matrix(2 * n, real=True, seed=9799) canonical, orthogonal = antisymmetric_canonical_form( antisymmetric_matrix) result_matrix = orthogonal.dot(antisymmetric_matrix.dot(orthogonal.T)) for i in numpy.ndindex(result_matrix.shape): self.assertAlmostEqual(result_matrix[i], canonical[i])
def test_diagonalizing_bogoliubov_transform_non_particle_conserving(self): """Test non-particle-conserving diagonalizing Bogoliubov transform.""" hermitian_part = self.quad_ham_npc.combined_hermitian_part antisymmetric_part = self.quad_ham_npc.antisymmetric_part block_matrix = numpy.zeros((2 * self.n_qubits, 2 * self.n_qubits), dtype=complex) block_matrix[:self.n_qubits, :self.n_qubits] = antisymmetric_part block_matrix[:self.n_qubits, self.n_qubits:] = hermitian_part block_matrix[self.n_qubits:, :self.n_qubits] = -hermitian_part.conj() block_matrix[self.n_qubits:, self.n_qubits:] = (-antisymmetric_part.conj()) _, transformation_matrix, _ = ( self.quad_ham_npc.diagonalizing_bogoliubov_transform()) left_block = transformation_matrix[:, :self.n_qubits] right_block = transformation_matrix[:, self.n_qubits:] ferm_unitary = numpy.zeros((2 * self.n_qubits, 2 * self.n_qubits), dtype=complex) ferm_unitary[:self.n_qubits, :self.n_qubits] = left_block ferm_unitary[:self.n_qubits, self.n_qubits:] = right_block ferm_unitary[self.n_qubits:, :self.n_qubits] = numpy.conjugate( right_block) ferm_unitary[self.n_qubits:, self.n_qubits:] = numpy.conjugate(left_block) # Check that the transformation is diagonalizing majorana_matrix, _ = self.quad_ham_npc.majorana_form() canonical, _ = antisymmetric_canonical_form(majorana_matrix) diagonalized = ferm_unitary.conj().dot( block_matrix.dot(ferm_unitary.T.conj())) for i in numpy.ndindex((2 * self.n_qubits, 2 * self.n_qubits)): self.assertAlmostEqual(diagonalized[i], canonical[i]) lower_unitary = ferm_unitary[self.n_qubits:] lower_left = lower_unitary[:, :self.n_qubits] lower_right = lower_unitary[:, self.n_qubits:] # Check that lower_left and lower_right satisfy the constraints # necessary for the transformed fermionic operators to satisfy # the fermionic anticommutation relations constraint_matrix_1 = (lower_left.dot(lower_left.T.conj()) + lower_right.dot(lower_right.T.conj())) constraint_matrix_2 = (lower_left.dot(lower_right.T) + lower_right.dot(lower_left.T)) identity = numpy.eye(self.n_qubits, dtype=complex) for i in numpy.ndindex((self.n_qubits, self.n_qubits)): self.assertAlmostEqual(identity[i], constraint_matrix_1[i]) self.assertAlmostEqual(0., constraint_matrix_2[i])
def test_canonical(self): """Test that the returned canonical matrix has the right form.""" n = 7 # Obtain a random antisymmetric matrix antisymmetric_matrix = random_antisymmetric_matrix(2 * n, real=True, seed=29206) canonical, _ = antisymmetric_canonical_form(antisymmetric_matrix) for i in range(2 * n): for j in range(2 * n): if i < n and j == n + i: self.assertTrue(canonical[i, j] >= 0.0) elif i >= n and j == i - n: self.assertTrue(canonical[i, j] < 0.0) else: self.assertAlmostEqual(canonical[i, j], 0.) diagonal = canonical[range(n), range(n, 2 * n)] for i in range(n - 1): self.assertTrue(diagonal[i] <= diagonal[i + 1])
def test_not_antisymmetric(self): n = 4 ones_mat = numpy.ones((n, n)) with self.assertRaises(ValueError): _ = antisymmetric_canonical_form(ones_mat)
def test_bad_dimensions(self): n, p = (3, 4) ones_mat = numpy.ones((n, p)) with self.assertRaises(ValueError): _ = antisymmetric_canonical_form(ones_mat)