mirror of https://github.com/Qiskit/qiskit.git
171 lines
6.3 KiB
Python
171 lines
6.3 KiB
Python
# This code is part of Qiskit.
|
|
#
|
|
# (C) Copyright IBM 2017, 2020.
|
|
#
|
|
# This code is licensed under the Apache License, Version 2.0. You may
|
|
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
|
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
|
#
|
|
# Any modifications or derivative works of this code must retain this
|
|
# copyright notice, and modified files need to carry a notice indicating
|
|
# that they have been altered from the originals.
|
|
|
|
|
|
"""HamiltonianGate tests"""
|
|
|
|
import numpy as np
|
|
from numpy.testing import assert_allclose
|
|
|
|
import qiskit
|
|
from qiskit.circuit.library import HamiltonianGate
|
|
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
|
|
from qiskit.circuit import Parameter
|
|
from qiskit.quantum_info import Operator
|
|
from qiskit.converters import circuit_to_dag, dag_to_circuit
|
|
from test import QiskitTestCase # pylint: disable=wrong-import-order
|
|
|
|
|
|
class TestHamiltonianGate(QiskitTestCase):
|
|
"""Tests for the HamiltonianGate class."""
|
|
|
|
def test_set_matrix(self):
|
|
"""Test instantiation"""
|
|
hamiltonian = HamiltonianGate([[0, 1], [1, 0]], 1)
|
|
self.assertEqual(hamiltonian.num_qubits, 1)
|
|
|
|
def test_set_matrix_raises(self):
|
|
"""test non-unitary"""
|
|
with self.assertRaises(ValueError):
|
|
HamiltonianGate([[1, 0], [1, 1]], 1)
|
|
|
|
def test_complex_time_raises(self):
|
|
"""test non-unitary"""
|
|
with self.assertRaises(ValueError):
|
|
HamiltonianGate([[1, 0], [1, 1]], 1j)
|
|
|
|
def test_conjugate(self):
|
|
"""test conjugate"""
|
|
ham = HamiltonianGate([[0, 1j], [-1j, 2]], np.pi / 4)
|
|
np.testing.assert_array_almost_equal(ham.conjugate().to_matrix(), np.conj(ham.to_matrix()))
|
|
|
|
def test_transpose(self):
|
|
"""test transpose"""
|
|
ham = HamiltonianGate([[15, 1j], [-1j, -2]], np.pi / 7)
|
|
np.testing.assert_array_almost_equal(
|
|
ham.transpose().to_matrix(), np.transpose(ham.to_matrix())
|
|
)
|
|
|
|
def test_adjoint(self):
|
|
"""test adjoint operation"""
|
|
ham = HamiltonianGate([[3, 4j], [-4j, -0.2]], np.pi * 0.143)
|
|
np.testing.assert_array_almost_equal(
|
|
ham.adjoint().to_matrix(), np.transpose(np.conj(ham.to_matrix()))
|
|
)
|
|
|
|
def test_repeat(self):
|
|
"""test repeat operation"""
|
|
ham = HamiltonianGate(np.array([[1, 0.5 + 4j], [0.5 - 4j, -0.2]]), np.pi * 0.143)
|
|
operator = Operator(ham)
|
|
self.assertTrue(np.allclose(Operator(ham.repeat(2)), operator @ operator))
|
|
|
|
|
|
class TestHamiltonianCircuit(QiskitTestCase):
|
|
"""Hamiltonian gate circuit tests."""
|
|
|
|
def test_1q_hamiltonian(self):
|
|
"""test 1 qubit hamiltonian"""
|
|
qr = QuantumRegister(1, "q0")
|
|
cr = ClassicalRegister(1, "c0")
|
|
qc = QuantumCircuit(qr, cr)
|
|
matrix = np.zeros((2, 2))
|
|
qc.x(qr[0])
|
|
theta = Parameter("theta")
|
|
qc.append(HamiltonianGate(matrix, theta), [qr[0]])
|
|
qc = qc.assign_parameters({theta: 1})
|
|
|
|
# test of text drawer
|
|
self.log.info(qc)
|
|
dag = circuit_to_dag(qc)
|
|
dag_nodes = dag.named_nodes("hamiltonian")
|
|
self.assertTrue(len(dag_nodes) == 1)
|
|
dnode = dag_nodes[0]
|
|
self.assertIsInstance(dnode.op, HamiltonianGate)
|
|
self.assertEqual(dnode.qargs, tuple(qc.qubits))
|
|
assert_allclose(dnode.op.to_matrix(), np.eye(2))
|
|
|
|
def test_2q_hamiltonian(self):
|
|
"""test 2 qubit hamiltonian"""
|
|
qr = QuantumRegister(2)
|
|
cr = ClassicalRegister(2)
|
|
qc = QuantumCircuit(qr, cr)
|
|
matrix = Operator.from_label("XY")
|
|
qc.x(qr[0])
|
|
theta = Parameter("theta")
|
|
uni2q = HamiltonianGate(matrix, theta)
|
|
qc.append(uni2q, [qr[0], qr[1]])
|
|
qc2 = qc.assign_parameters({theta: -np.pi / 2})
|
|
dag = circuit_to_dag(qc2)
|
|
nodes = dag.two_qubit_ops()
|
|
self.assertEqual(len(nodes), 1)
|
|
dnode = nodes[0]
|
|
self.assertIsInstance(dnode.op, HamiltonianGate)
|
|
self.assertEqual(dnode.qargs, (qr[0], qr[1]))
|
|
# Equality based on Pauli exponential identity
|
|
np.testing.assert_array_almost_equal(dnode.op.to_matrix(), 1j * matrix.data)
|
|
qc3 = dag_to_circuit(dag)
|
|
self.assertEqual(qc2, qc3)
|
|
|
|
def test_3q_hamiltonian(self):
|
|
"""test 3 qubit hamiltonian on non-consecutive bits"""
|
|
qr = QuantumRegister(4)
|
|
qc = QuantumCircuit(qr)
|
|
qc.x(qr[0])
|
|
matrix = Operator.from_label("XZY")
|
|
theta = Parameter("theta")
|
|
uni3q = HamiltonianGate(matrix, theta)
|
|
qc.append(uni3q, [qr[0], qr[1], qr[3]])
|
|
qc.cx(qr[3], qr[2])
|
|
# test of text drawer
|
|
self.log.info(qc)
|
|
qc = qc.assign_parameters({theta: -np.pi / 2})
|
|
dag = circuit_to_dag(qc)
|
|
nodes = dag.multi_qubit_ops()
|
|
self.assertEqual(len(nodes), 1)
|
|
dnode = nodes[0]
|
|
self.assertIsInstance(dnode.op, HamiltonianGate)
|
|
self.assertEqual(dnode.qargs, (qr[0], qr[1], qr[3]))
|
|
np.testing.assert_almost_equal(dnode.op.to_matrix(), 1j * matrix.data)
|
|
|
|
def test_qobj_with_hamiltonian(self):
|
|
"""test qobj output with hamiltonian
|
|
REMOVE once Qobj gets removed"""
|
|
qr = QuantumRegister(4)
|
|
qc = QuantumCircuit(qr)
|
|
qc.rx(np.pi / 4, qr[0])
|
|
matrix = Operator.from_label("XIZ")
|
|
theta = Parameter("theta")
|
|
uni = HamiltonianGate(matrix, theta, label="XIZ")
|
|
qc.append(uni, [qr[0], qr[1], qr[3]])
|
|
qc.cx(qr[3], qr[2])
|
|
qc = qc.assign_parameters({theta: np.pi / 2})
|
|
with self.assertWarns(DeprecationWarning):
|
|
qobj = qiskit.compiler.assemble(qc)
|
|
instr = qobj.experiments[0].instructions[1]
|
|
self.assertEqual(instr.name, "hamiltonian")
|
|
# Also test label
|
|
self.assertEqual(instr.label, "XIZ")
|
|
np.testing.assert_array_almost_equal(
|
|
np.array(instr.params[0]).astype(np.complex64), matrix.data
|
|
)
|
|
|
|
def test_decomposes_into_correct_unitary(self):
|
|
"""test 2 qubit hamiltonian"""
|
|
qc = QuantumCircuit(2)
|
|
matrix = Operator.from_label("XY")
|
|
theta = Parameter("theta")
|
|
uni2q = HamiltonianGate(matrix, theta)
|
|
qc.append(uni2q, [0, 1])
|
|
qc = qc.assign_parameters({theta: -np.pi / 2}).decompose()
|
|
decomposed_ham = qc.data[0].operation
|
|
self.assertEqual(Operator(decomposed_ham), 1j * Operator.from_label("XY"))
|