diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cd87f5..77ba2cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# Release 0.30.0-dev +# Release 0.32.0-dev ### New features since last release @@ -6,6 +6,9 @@ ### Improvements +* Added support for `qml.StatePrep` as a state preparation operation. + [(#54)](https://github.com/PennyLaneAI/pennylane-qulacs/pull/54) + ### Documentation ### Bug fixes @@ -14,6 +17,8 @@ This release contains contributions from (in alphabetical order): +Jay Soni + --- # Release 0.29.0 diff --git a/pennylane_qulacs/qulacs_device.py b/pennylane_qulacs/qulacs_device.py index 216310f..88628ca 100644 --- a/pennylane_qulacs/qulacs_device.py +++ b/pennylane_qulacs/qulacs_device.py @@ -21,7 +21,15 @@ import numpy as np from pennylane import QubitDevice, DeviceError -from pennylane.ops import QubitStateVector, BasisState, QubitUnitary, CRZ, PhaseShift, Adjoint +from pennylane.ops import ( + QubitStateVector, + BasisState, + QubitUnitary, + CRZ, + PhaseShift, + Adjoint, + StatePrep, +) import qulacs.gate as gate from qulacs import QuantumCircuit, QuantumState, Observable @@ -85,6 +93,7 @@ class QulacsDevice(QubitDevice): } _operation_map = { + "StatePrep": None, "QubitStateVector": None, "BasisState": None, "QubitUnitary": None, @@ -159,7 +168,7 @@ def apply_operations(self, operations): """ for i, op in enumerate(operations): - if i > 0 and isinstance(op, (QubitStateVector, BasisState)): + if i > 0 and isinstance(op, (QubitStateVector, BasisState, StatePrep)): raise DeviceError( "Operation {} cannot be used after other Operations have already been applied " "on a {} device.".format(op.name, self.short_name) @@ -169,7 +178,7 @@ def apply_operations(self, operations): inverse = True op = op.base - if isinstance(op, QubitStateVector): + if isinstance(op, (QubitStateVector, StatePrep)): self._apply_qubit_state_vector(op) elif isinstance(op, BasisState): self._apply_basis_state(op) diff --git a/requirements.txt b/requirements.txt index 0cab76b..1973f92 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ -pennylane>=0.15 +git+https://github.com/PennyLaneAI/pennylane.git Qulacs>=0.1.10.1 numpy~=1.16 diff --git a/tests/test_apply.py b/tests/test_apply.py index a8991f0..3b24e3a 100755 --- a/tests/test_apply.py +++ b/tests/test_apply.py @@ -163,12 +163,13 @@ def test_basis_state_on_wires_subset(self, state, device_wires, op_wires, tol): expected = dev._expand_state(expected, op_wires) assert np.allclose(res, expected, tol) - def test_qubit_state_vector(self, init_state, tol): - """Test QubitStateVector application""" + @pytest.mark.parametrize("state_prep_op", (qml.QubitStateVector, qml.StatePrep)) + def test_qubit_state_vector(self, init_state, state_prep_op, tol): + """Test QubitStateVector and StatePrep application""" dev = QulacsDevice(1) state = init_state(1) - op = qml.QubitStateVector(state, wires=[0]) + op = state_prep_op(state, wires=[0]) dev.apply([op]) dev._obs_queue = [] @@ -176,14 +177,15 @@ def test_qubit_state_vector(self, init_state, tol): expected = state assert np.allclose(res, expected, tol) + @pytest.mark.parametrize("state_prep_op", (qml.QubitStateVector, qml.StatePrep)) @pytest.mark.parametrize("device_wires", [3, 4, 5]) @pytest.mark.parametrize("op_wires", [[0], [2], [0, 1], [1, 0], [2, 0]]) - def test_qubit_state_vector_on_wires_subset(self, init_state, device_wires, op_wires, tol): - """Test QubitStateVector application on a subset of device wires""" + def test_qubit_state_vector_on_wires_subset(self, init_state, device_wires, op_wires, state_prep_op, tol): + """Test QubitStateVector and StatePrep application on a subset of device wires""" dev = QulacsDevice(device_wires) state = init_state(len(op_wires)) - op = qml.QubitStateVector(state, wires=op_wires) + op = state_prep_op(state, wires=op_wires) dev.apply([op]) dev._obs_queue = [] @@ -198,7 +200,7 @@ def test_single_qubit_no_parameters(self, init_state, op, mat, tol): dev = QulacsDevice(1) state = init_state(1) - dev.apply([qml.QubitStateVector(state, wires=[0]), op]) + dev.apply([qml.StatePrep(state, wires=[0]), op]) dev._obs_queue = [] res = dev.state @@ -213,7 +215,7 @@ def test_single_qubit_parameters(self, init_state, op, func, theta, tol): state = init_state(1) op.data = [theta] - dev.apply([qml.QubitStateVector(state, wires=[0]), op]) + dev.apply([qml.StatePrep(state, wires=[0]), op]) dev._obs_queue = [] res = dev.state @@ -226,7 +228,7 @@ def test_two_qubit_no_parameters(self, init_state, op, mat, tol): dev = QulacsDevice(2) state = init_state(2) - dev.apply([qml.QubitStateVector(state, wires=[0, 1]), op]) + dev.apply([qml.StatePrep(state, wires=[0, 1]), op]) dev._obs_queue = [] res = dev.state @@ -242,7 +244,7 @@ def test_qubit_unitary(self, init_state, mat, tol): state = init_state(N) op = qml.QubitUnitary(mat, wires=list(range(N))) - dev.apply([qml.QubitStateVector(state, wires=list(range(N))), op]) + dev.apply([qml.StatePrep(state, wires=list(range(N))), op]) dev._obs_queue = [] res = dev.state @@ -262,7 +264,7 @@ def test_three_qubit_no_parameters(self, init_state, op, mat, tol): dev = QulacsDevice(3) state = init_state(3) - dev.apply([qml.QubitStateVector(state, wires=[0, 1, 2]), op]) + dev.apply([qml.StatePrep(state, wires=[0, 1, 2]), op]) dev._obs_queue = [] res = dev.state @@ -277,7 +279,7 @@ def test_two_qubit_parameters(self, init_state, op, func, theta, tol): state = init_state(2) op.data = [theta] - dev.apply([qml.QubitStateVector(state, wires=[0, 1]), op]) + dev.apply([qml.StatePrep(state, wires=[0, 1]), op]) dev._obs_queue = []