class TestReset: """Unit tests for the method `reset()`""" def test_reset_basis(self, nr_wires, tol): dev = qml.device("default.mixed", wires=nr_wires) dev._state = dev._create_basis_state(1) dev.reset() assert np.allclose(dev._state, dev._create_basis_state(0), atol=tol, rtol=0) @pytest.mark.parametrize("op", [CNOT, CZ]) def test_reset_after_twoqubit(self, nr_wires, op, tol): """Tests that state is correctly reset after applying two-qubit operations on the first wires""" dev = qml.device("default.mixed", wires=nr_wires) dev.apply([op(wires=[0, 1])]) dev.reset() assert np.allclose(dev._state, dev._create_basis_state(0), atol=tol, rtol=0) @pytest.mark.parametrize( "op", [ AmplitudeDamping(0.5, wires=[0]), DepolarizingChannel(0.5, wires=[0]), ResetError(0.1, 0.5, wires=[0]), PauliError("X", 0.5, wires=0), PauliError("ZY", 0.3, wires=[1, 0]), ], ) def test_reset_after_channel(self, nr_wires, op, tol): """Tests that state is correctly reset after applying a channel on the first wires""" dev = qml.device("default.mixed", wires=nr_wires) dev.apply([op]) dev.reset() assert np.allclose(dev._state, dev._create_basis_state(0), atol=tol, rtol=0) @pytest.mark.parametrize("op", [PauliX, PauliZ, Hadamard]) def test_reset_after_channel(self, nr_wires, op, tol): """Tests that state is correctly reset after applying gates on the first wire""" dev = qml.device("default.mixed", wires=nr_wires) dev.apply([op(wires=0)]) dev.reset() assert np.allclose(dev._state, dev._create_basis_state(0), atol=tol, rtol=0)
def test_max_mixed_state(self, nr_wires, tol): """Tests that applying damping channel on all qubits to the state |11...1> produces a maximally mixed state""" dev = qml.device("default.mixed", wires=nr_wires) flips = [PauliX(i) for i in range(nr_wires)] damps = [AmplitudeDamping(0.5, wires=i) for i in range(nr_wires)] ops = flips + damps dev.apply(ops) assert np.allclose(dev.state, max_mixed_state(nr_wires), atol=tol, rtol=0)
class TestKrausOps: """Unit tests for the method `_get_kraus_ops()`""" unitary_ops = [ (PauliX, np.array([[0, 1], [1, 0]])), (Hadamard, np.array([[INV_SQRT2, INV_SQRT2], [INV_SQRT2, -INV_SQRT2]])), (CNOT, np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]])), ] @pytest.mark.parametrize("ops", unitary_ops) def test_unitary_kraus(self, ops, tol): """Tests that matrices of non-diagonal unitary operations are retrieved correctly""" dev = qml.device("default.mixed", wires=2) assert np.allclose(dev._get_kraus(ops[0]), [ops[1]], atol=tol, rtol=0) diagonal_ops = [ (PauliZ(wires=0), np.array([1, -1])), (CZ(wires=[0, 1]), np.array([1, 1, 1, -1])), ] @pytest.mark.parametrize("ops", diagonal_ops) def test_diagonal_kraus(self, ops, tol): """Tests that matrices of non-diagonal unitary operations are retrieved correctly""" dev = qml.device("default.mixed", wires=2) assert np.allclose(dev._get_kraus(ops[0]), ops[1], atol=tol, rtol=0) p = 0.5 K0 = np.sqrt(1 - p) * np.eye(2) K1 = np.sqrt(p / 3) * np.array([[0, 1], [1, 0]]) K2 = np.sqrt(p / 3) * np.array([[0, -1j], [1j, 0]]) K3 = np.sqrt(p / 3) * np.array([[1, 0], [0, -1]]) channel_ops = [ ( AmplitudeDamping(p, wires=0), [ np.diag([1, np.sqrt(1 - p)]), np.sqrt(p) * np.array([[0, 1], [0, 0]]) ], ), (DepolarizingChannel(p, wires=0), [K0, K1, K2, K3]), ] @pytest.mark.parametrize("ops", channel_ops) def test_channel_kraus(self, ops, tol): """Tests that kraus matrices of non-unitary channels are retrieved correctly""" dev = qml.device("default.mixed", wires=1) assert np.allclose(dev._get_kraus(ops[0]), ops[1], atol=tol, rtol=0)
class TestState: """Tests for the method `state()`, which retrieves the state of the system""" def test_shape(self, nr_wires): """Tests that the state has the correct shape""" dev = qml.device("default.mixed", wires=nr_wires) assert (2**nr_wires, 2**nr_wires) == np.shape(dev.state) def test_init_state(self, nr_wires, tol): """Tests that the state is |0...0><0...0| after initialization of the device""" rho = np.zeros((2**nr_wires, 2**nr_wires)) rho[0, 0] = 1 dev = qml.device("default.mixed", wires=nr_wires) assert np.allclose(rho, dev.state, atol=tol, rtol=0) @pytest.mark.parametrize("op", [CNOT, CZ]) def test_state_after_twoqubit(self, nr_wires, op, tol): """Tests that state is correctly retrieved after applying two-qubit operations on the first wires""" dev = qml.device("default.mixed", wires=nr_wires) dev.apply([op(wires=[0, 1])]) current_state = np.reshape(dev._state, (2**nr_wires, 2**nr_wires)) assert np.allclose(dev.state, current_state, atol=tol, rtol=0) @pytest.mark.parametrize( "op", [ AmplitudeDamping(0.5, wires=0), DepolarizingChannel(0.5, wires=0), ResetError(0.1, 0.5, wires=0), PauliError("X", 0.5, wires=0), PauliError("ZY", 0.3, wires=[1, 0]), ], ) def test_state_after_channel(self, nr_wires, op, tol): """Tests that state is correctly retrieved after applying a channel on the first wires""" dev = qml.device("default.mixed", wires=nr_wires) dev.apply([op]) current_state = np.reshape(dev._state, (2**nr_wires, 2**nr_wires)) assert np.allclose(dev.state, current_state, atol=tol, rtol=0) @pytest.mark.parametrize("op", [PauliX, PauliZ, Hadamard]) def test_state_after_gate(self, nr_wires, op, tol): """Tests that state is correctly retrieved after applying operations on the first wires""" dev = qml.device("default.mixed", wires=nr_wires) dev.apply([op(wires=0)]) current_state = np.reshape(dev._state, (2**nr_wires, 2**nr_wires)) assert np.allclose(dev.state, current_state, atol=tol, rtol=0)
class TestApplyChannel: """Unit tests for the method `_apply_channel()`""" x_apply_channel_init = [ [1, PauliX, basis_state(1, 1)], [ 1, Hadamard, np.array([[0.5 + 0.0j, 0.5 + 0.0j], [0.5 + 0.0j, 0.5 + 0.0j]]) ], [2, CNOT, basis_state(0, 2)], [1, AmplitudeDamping(0.5, wires=0), basis_state(0, 1)], [ 1, DepolarizingChannel(0.5, wires=0), np.array([[2 / 3 + 0.0j, 0.0 + 0.0j], [0.0 + 0.0j, 1 / 3 + 0.0j]]), ], [ 1, ResetError(0.1, 0.5, wires=0), np.array([[0.5 + 0.0j, 0.0 + 0.0j], [0.0 + 0.0j, 0.5 + 0.0j]]), ], ] @pytest.mark.parametrize("x", x_apply_channel_init) def test_channel_init(self, x, tol): """Tests that channels are correctly applied to the default initial state""" nr_wires = x[0] op = x[1] target_state = np.reshape(x[2], [2] * 2 * nr_wires) dev = qml.device("default.mixed", wires=nr_wires) kraus = dev._get_kraus(op) if op == CNOT: dev._apply_channel(kraus, wires=Wires([0, 1])) else: dev._apply_channel(kraus, wires=Wires(0)) assert np.allclose(dev._state, target_state, atol=tol, rtol=0) x_apply_channel_mixed = [ [1, PauliX, max_mixed_state(1)], [2, Hadamard, max_mixed_state(2)], [2, CNOT, max_mixed_state(2)], [ 1, AmplitudeDamping(0.5, wires=0), np.array([[0.75 + 0.0j, 0.0 + 0.0j], [0.0 + 0.0j, 0.25 + 0.0j]]), ], [ 1, DepolarizingChannel(0.5, wires=0), np.array([[0.5 + 0.0j, 0.0 + 0.0j], [0.0 + 0.0j, 0.5 + 0.0j]]), ], [ 1, ResetError(0.1, 0.5, wires=0), np.array([[0.3 + 0.0j, 0.0 + 0.0j], [0.0 + 0.0j, 0.7 + 0.0j]]), ], ] @pytest.mark.parametrize("x", x_apply_channel_mixed) def test_channel_mixed(self, x, tol): """Tests that channels are correctly applied to the maximally mixed state""" nr_wires = x[0] op = x[1] target_state = np.reshape(x[2], [2] * 2 * nr_wires) dev = qml.device("default.mixed", wires=nr_wires) max_mixed = np.reshape(max_mixed_state(nr_wires), [2] * 2 * nr_wires) dev._state = max_mixed kraus = dev._get_kraus(op) if op == CNOT: dev._apply_channel(kraus, wires=Wires([0, 1])) else: dev._apply_channel(kraus, wires=Wires(0)) assert np.allclose(dev._state, target_state, atol=tol, rtol=0) x_apply_channel_root = [ [ 1, PauliX, np.array([[0.5 + 0.0j, -0.5 + 0.0j], [-0.5 - 0.0j, 0.5 + 0.0j]]) ], [ 1, Hadamard, np.array([[0.0 + 0.0j, 0.0 + 0.0j], [0.0 + 0.0j, 1.0 + 0.0j]]) ], [ 2, CNOT, np.array([ [0.25 + 0.0j, 0.0 - 0.25j, 0.0 + 0.25j, -0.25], [0.0 + 0.25j, 0.25 + 0.0j, -0.25 + 0.0j, 0.0 - 0.25j], [0.0 - 0.25j, -0.25 + 0.0j, 0.25 + 0.0j, 0.0 + 0.25j], [-0.25 + 0.0j, 0.0 + 0.25j, 0.0 - 0.25j, 0.25 + 0.0j], ]), ], [ 1, AmplitudeDamping(0.5, wires=0), np.array([[0.75 + 0.0j, -0.35355339 - 0.0j], [-0.35355339 + 0.0j, 0.25 + 0.0j]]), ], [ 1, DepolarizingChannel(0.5, wires=0), np.array([[0.5 + 0.0j, -1 / 6 + 0.0j], [-1 / 6 + 0.0j, 0.5 + 0.0j]]), ], [ 1, ResetError(0.1, 0.5, wires=0), np.array([[0.3 + 0.0j, -0.2 + 0.0j], [-0.2 + 0.0j, 0.7 + 0.0j]]), ], ] @pytest.mark.parametrize("x", x_apply_channel_root) def test_channel_root(self, x, tol): """Tests that channels are correctly applied to root state""" nr_wires = x[0] op = x[1] target_state = np.reshape(x[2], [2] * 2 * nr_wires) dev = qml.device("default.mixed", wires=nr_wires) root = np.reshape(root_state(nr_wires), [2] * 2 * nr_wires) dev._state = root kraus = dev._get_kraus(op) if op == CNOT: dev._apply_channel(kraus, wires=Wires([0, 1])) else: dev._apply_channel(kraus, wires=Wires(0)) assert np.allclose(dev._state, target_state, atol=tol, rtol=0)