Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for StatePrep #54

Merged
merged 4 commits into from
Aug 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
# Release 0.30.0-dev
# Release 0.32.0-dev

### New features since last release

### Breaking changes

### Improvements

* Added support for `qml.StatePrep` as a state preparation operation.
[(#54)](https://github.com/PennyLaneAI/pennylane-qulacs/pull/54)

### Documentation

### Bug fixes
Expand All @@ -14,6 +17,8 @@

This release contains contributions from (in alphabetical order):

Jay Soni

---
# Release 0.29.0

Expand Down
15 changes: 12 additions & 3 deletions pennylane_qulacs/qulacs_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -85,6 +93,7 @@ class QulacsDevice(QubitDevice):
}

_operation_map = {
"StatePrep": None,
"QubitStateVector": None,
"BasisState": None,
"QubitUnitary": None,
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
pennylane>=0.15
git+https://github.com/PennyLaneAI/pennylane.git
Qulacs>=0.1.10.1
numpy~=1.16
26 changes: 14 additions & 12 deletions tests/test_apply.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,27 +163,29 @@ 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 = []

res = dev.state
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 = []

Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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 = []

Expand Down
Loading