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

[Code Together] Adding SISWAP operation #1563

Merged
merged 41 commits into from
Aug 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
15592e1
Initial work for SISWAP
charmerDark Aug 19, 2021
cb899ec
Merge branch 'siswap_branch' of https://github.com/charmerDark/pennyl…
charmerDark Aug 19, 2021
3f612d6
bug fixes
charmerDark Aug 19, 2021
8783790
some more bug fixes
charmerDark Aug 19, 2021
977ce9b
bug fixing
charmerDark Aug 19, 2021
9e50019
bug fixes
charmerDark Aug 19, 2021
93e61c6
bug_fixes
charmerDark Aug 19, 2021
233aa1b
Merge branch 'PennyLaneAI:master' into siswap_branch
charmerDark Aug 19, 2021
965cc50
buug fixes
charmerDark Aug 20, 2021
acc4e9f
Merge branch 'siswap_branch' of https://github.com/charmerDark/pennyl…
charmerDark Aug 20, 2021
73f4fe0
added tests
charmerDark Aug 20, 2021
cfdc052
completed tests
charmerDark Aug 20, 2021
489d159
Merge branch 'master' into siswap_branch
antalszava Aug 20, 2021
7fbe8e2
fixing tests
charmerDark Aug 20, 2021
a0696a8
Merge branch 'siswap_branch' of https://github.com/charmerDark/pennyl…
charmerDark Aug 20, 2021
b9d2d01
format fix for tests/devices and fix in default_qubit.py
charmerDark Aug 20, 2021
11d0a13
fixing tests
charmerDark Aug 20, 2021
d62290b
fixing gate_data.py matrix for SISWAP
charmerDark Aug 20, 2021
6e4a183
fixing styling in tests/gate_data.py
charmerDark Aug 20, 2021
4b9cae9
Merge branch 'master' into siswap_branch
antalszava Aug 20, 2021
d921f43
Merge branch 'master' into siswap_branch
antalszava Aug 21, 2021
5dfb9ae
Update pennylane/ops/__init__.py
charmerDark Aug 21, 2021
1f1951c
added tests for sqisw to test_default_qubit.py and test_qubit_ops.py
charmerDark Aug 21, 2021
be470d2
fixing tests for sisqw
charmerDark Aug 21, 2021
c16c635
adding SQISW to doc/introduction/operations.rst
charmerDark Aug 21, 2021
f47560f
Merge branch 'master' into siswap_branch
charmerDark Aug 22, 2021
82908ae
Merge branch 'master' into siswap_branch
antalszava Aug 23, 2021
4afbfc7
Merge branch 'master' into siswap_branch
antalszava Aug 23, 2021
77b486f
Update pennylane/ops/qubit/non_parametric_ops.py
charmerDark Aug 23, 2021
83344ea
Update pennylane/ops/qubit/non_parametric_ops.py
charmerDark Aug 23, 2021
1f1497a
Update tests/ops/test_qubit_ops.py
charmerDark Aug 23, 2021
c44ce36
Update pennylane/ops/qubit/non_parametric_ops.py
charmerDark Aug 23, 2021
83198a1
Update tests/ops/test_qubit_ops.py
charmerDark Aug 23, 2021
7f74273
Update tests/ops/test_qubit_ops.py
charmerDark Aug 23, 2021
3344580
Update tests/ops/test_qubit_ops.py
charmerDark Aug 23, 2021
bf9e718
Update tests/ops/test_qubit_ops.py
charmerDark Aug 23, 2021
2d3f60d
Update tests/ops/test_qubit_ops.py
charmerDark Aug 23, 2021
86a9534
updating test_default_qubit.py
charmerDark Aug 23, 2021
c540c6b
styling fix for tests/ops/test_qunit_ops.py
charmerDark Aug 23, 2021
bcca75d
Update pennylane/ops/qubit/non_parametric_ops.py
antalszava Aug 23, 2021
a4120f1
Update .github/CHANGELOG.md
antalszava Aug 23, 2021
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
5 changes: 4 additions & 1 deletion .github/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

<h3>New features since last release</h3>

* Added a new `SISWAP` operation and a `SQISW` alias with support to the `default_qubit` device.
[#1563](https://github.com/PennyLaneAI/pennylane/pull/1563)

* The `RotosolveOptimizer` now can tackle general parametrized circuits, and is no longer
restricted to single-qubit Pauli rotations.
[(#1489)](https://github.com/PennyLaneAI/pennylane/pull/1489)
Expand Down Expand Up @@ -262,7 +265,7 @@ and requirements-ci.txt (unpinned). This latter would be used by the CI.
This release contains contributions from (in alphabetical order):


Akash Narayanan B, Thomas Bromley, Tanya Garg, Josh Izaac, Prateek Jain, Johannes Jakob Meyer, Maria Schuld,
Vishnu Ajith, Akash Narayanan B, Thomas Bromley, Tanya Garg, Josh Izaac, Prateek Jain, Johannes Jakob Meyer, Maria Schuld,
Ingrid Strandberg, David Wierichs, Vincent Wong.


Expand Down
2 changes: 2 additions & 0 deletions doc/introduction/operations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ Qubit gates
~pennylane.CY
~pennylane.SWAP
~pennylane.ISWAP
~pennylane.SISWAP
~pennylane.SQISW
~pennylane.IsingXX
~pennylane.IsingYY
~pennylane.IsingZZ
Expand Down
2 changes: 2 additions & 0 deletions pennylane/devices/default_qubit.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ class DefaultQubit(QubitDevice):
"CNOT",
"SWAP",
"ISWAP",
"SISWAP",
"SQISW",
"CSWAP",
"Toffoli",
"CY",
Expand Down
2 changes: 2 additions & 0 deletions pennylane/ops/qubit/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@
"CY",
"SWAP",
"ISWAP",
"SISWAP",
"SQISW",
"CSWAP",
"Toffoli",
"RX",
Expand Down
63 changes: 63 additions & 0 deletions pennylane/ops/qubit/non_parametric_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,69 @@ def adjoint(self):
return ISWAP(wires=self.wires).inv()


class SISWAP(Operation):
r"""SISWAP(wires)
The square root of i-swap operator. Can also be accessed as ``qml.SQISW``

.. math:: SISWAP = \begin{bmatrix}
1 & 0 & 0 & 0 \\
0 & 1/ \sqrt{2} & i/\sqrt{2} & 0\\
0 & i/ \sqrt{2} & 1/ \sqrt{2} & 0\\
0 & 0 & 0 & 1
\end{bmatrix}.

**Details:**

* Number of wires: 2
* Number of parameters: 0

Args:
wires (Sequence[int]): the wires the operation acts on
"""
num_params = 0
num_wires = 2
par_domain = None

@classmethod
def _matrix(cls, *params):
return np.array(
[
[1, 0, 0, 0],
[0, INV_SQRT2, INV_SQRT2 * 1j, 0],
[0, INV_SQRT2 * 1j, INV_SQRT2, 0],
[0, 0, 0, 1],
]
)

@classmethod
def _eigvals(cls, *params):
return np.array([INV_SQRT2 * (1 + 1j), INV_SQRT2 * (1 - 1j), 1, 1])

@staticmethod
def decomposition(wires):
decomp_ops = [
SX(wires=wires[0]),
qml.RZ(np.pi / 2, wires=wires[0]),
CNOT(wires=[wires[0], wires[1]]),
SX(wires=wires[0]),
qml.RZ(7 * np.pi / 4, wires=wires[0]),
SX(wires=wires[0]),
qml.RZ(np.pi / 2, wires=wires[0]),
SX(wires=wires[1]),
qml.RZ(7 * np.pi / 4, wires=wires[1]),
CNOT(wires=[wires[0], wires[1]]),
SX(wires=wires[0]),
SX(wires=wires[1]),
]
return decomp_ops

def adjoint(self):
return SISWAP(wires=self.wires).inv()


SQISW = SISWAP


class CSWAP(Operation):
r"""CSWAP(wires)
The controlled-swap operator
Expand Down
59 changes: 57 additions & 2 deletions tests/devices/test_default_qubit.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,57 @@ def test_apply_operation_single_wire_no_parameters_inverse(
),
]

all_two_wires_no_parameters = test_data_two_wires_no_parameters + test_data_iswap
test_data_siswap = [
(qml.SISWAP, [1, 0, 0, 0], [1, 0, 0, 0]),
(qml.SISWAP, [0, 1, 0, 0], [0, 1 / math.sqrt(2), 1 / math.sqrt(2) * 1j, 0]),
(
qml.SISWAP,
[1 / math.sqrt(2), 1 / math.sqrt(2), 0, 0],
[1 / math.sqrt(2), 0.5, 0.5 * 1j, 0],
),
]

test_data_sqisw = [
charmerDark marked this conversation as resolved.
Show resolved Hide resolved
(qml.SQISW, [1, 0, 0, 0], [1, 0, 0, 0]),
(qml.SQISW, [0, 1, 0, 0], [0, 1 / math.sqrt(2), 1 / math.sqrt(2) * 1j, 0]),
(
qml.SQISW,
[1 / math.sqrt(2), 1 / math.sqrt(2), 0, 0],
[1 / math.sqrt(2), 0.5, 0.5 * 1j, 0],
),
]

test_data_siswap_inv = [
(
qml.SISWAP,
[1 / math.sqrt(2), 0, 1 / math.sqrt(2), 0],
[1 / math.sqrt(2), -0.5 * 1j, 0.5, 0],
),
(qml.SISWAP, [0, 0, 1, 0], [0, -1 / math.sqrt(2) * 1j, 1 / math.sqrt(2), 0]),
(
qml.SISWAP,
[1 / math.sqrt(2), 0, -1 / math.sqrt(2), 0],
[1 / math.sqrt(2), 0.5 * 1j, -0.5, 0],
),
]

test_data_sqisw_inv = [
charmerDark marked this conversation as resolved.
Show resolved Hide resolved
(
qml.SQISW,
[1 / math.sqrt(2), 0, 1 / math.sqrt(2), 0],
[1 / math.sqrt(2), -0.5 * 1j, 0.5, 0],
),
(qml.SQISW, [0, 0, 1, 0], [0, -1 / math.sqrt(2) * 1j, 1 / math.sqrt(2), 0]),
(
qml.SQISW,
[1 / math.sqrt(2), 0, -1 / math.sqrt(2), 0],
[1 / math.sqrt(2), 0.5 * 1j, -0.5, 0],
),
]

all_two_wires_no_parameters = (
test_data_two_wires_no_parameters + test_data_iswap + test_data_siswap + test_data_sqisw
)

@pytest.mark.parametrize("operation,input,expected_output", all_two_wires_no_parameters)
def test_apply_operation_two_wires_no_parameters(
Expand All @@ -240,7 +290,12 @@ def test_apply_operation_two_wires_no_parameters(
qubit_device_2_wires._state.flatten(), np.array(expected_output), atol=tol, rtol=0
)

all_two_wires_no_parameters_inv = test_data_two_wires_no_parameters + test_data_iswap_inv
all_two_wires_no_parameters_inv = (
test_data_two_wires_no_parameters
+ test_data_iswap_inv
+ test_data_siswap_inv
+ test_data_sqisw_inv
)

@pytest.mark.parametrize("operation,input,expected_output", all_two_wires_no_parameters_inv)
def test_apply_operation_two_wires_no_parameters_inverse(
Expand Down
8 changes: 8 additions & 0 deletions tests/gate_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@
CNOT = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]) #: CNOT gate
SWAP = np.array([[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]]) #: SWAP gate
ISWAP = np.array([[1, 0, 0, 0], [0, 0, 1j, 0], [0, 1j, 0, 0], [0, 0, 0, 1]]) #: ISWAP gate
SISWAP = np.array(
[
[1, 0, 0, 0],
[0, 1 / math.sqrt(2), 1 / math.sqrt(2) * 1j, 0],
[0, 1 / math.sqrt(2) * 1j, 1 / math.sqrt(2), 0],
[0, 0, 0, 1],
]
)
CZ = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, -1]]) #: CZ gate
S = np.array([[1, 0], [0, 1j]]) #: Phase Gate
T = np.array([[1, 0], [0, cmath.exp(1j * np.pi / 4)]]) #: T Gate
Expand Down
61 changes: 61 additions & 0 deletions tests/ops/test_qubit_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
CNOT,
SWAP,
ISWAP,
SISWAP,
CZ,
S,
T,
Expand Down Expand Up @@ -400,6 +401,7 @@ def circuit(basis_state):
(qml.CNOT, CNOT),
(qml.SWAP, SWAP),
(qml.ISWAP, ISWAP),
(qml.SISWAP, SISWAP),
(qml.CZ, CZ),
(qml.S, S),
(qml.T, T),
Expand All @@ -419,6 +421,8 @@ def circuit(basis_state):
qml.CY(wires=[0, 1]),
qml.SWAP(wires=[0, 1]),
qml.ISWAP(wires=[0, 1]),
qml.SISWAP(wires=[0, 1]),
qml.SQISW(wires=[0, 1]),
qml.CSWAP(wires=[0, 1, 2]),
qml.PauliRot(0.123, "Y", wires=0),
qml.IsingXX(0.123, wires=[0, 1]),
Expand Down Expand Up @@ -772,6 +776,55 @@ def test_ISWAP_decomposition(self, tol):

assert np.allclose(decomposed_matrix, op.matrix, atol=tol, rtol=0)

@pytest.mark.parametrize("siswap_op", [qml.SISWAP, qml.SQISW])
def test_SISWAP_decomposition(self, siswap_op, tol):
"""Tests that the decomposition of the SISWAP gate and its SQISW alias gate is correct"""
op = siswap_op(wires=[0, 1])
res = op.decomposition(op.wires)

assert len(res) == 12

assert res[0].wires == Wires([0])
assert res[1].wires == Wires([0])
assert res[2].wires == Wires([0, 1])
assert res[3].wires == Wires([0])
assert res[4].wires == Wires([0])
assert res[5].wires == Wires([0])
assert res[6].wires == Wires([0])
assert res[7].wires == Wires([1])
assert res[8].wires == Wires([1])
assert res[9].wires == Wires([0, 1])
assert res[10].wires == Wires([0])
assert res[11].wires == Wires([1])

assert res[0].name == "SX"
assert res[1].name == "RZ"
assert res[2].name == "CNOT"
assert res[3].name == "SX"
assert res[4].name == "RZ"
assert res[5].name == "SX"
assert res[6].name == "RZ"
assert res[7].name == "SX"
assert res[8].name == "RZ"
assert res[9].name == "CNOT"
assert res[10].name == "SX"
assert res[11].name == "SX"

mats = []
for i in reversed(res):
if i.wires == Wires([1]):
mats.append(np.kron(np.eye(2), i.matrix))
elif i.wires == Wires([0]):
mats.append(np.kron(i.matrix, np.eye(2)))
elif i.wires == Wires([1, 0]) and i.name == "CNOT":
mats.append(np.array([[1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0]]))
else:
mats.append(i.matrix)

decomposed_matrix = np.linalg.multi_dot(mats)

assert np.allclose(decomposed_matrix, op.matrix, atol=tol, rtol=0)

def test_isingxx_decomposition(self, tol):
"""Tests that the decomposition of the IsingXX gate is correct"""
param = 0.1234
Expand Down Expand Up @@ -1536,6 +1589,14 @@ def test_iswap_eigenval(self):
res = op.eigvals
assert np.allclose(res, exp)

@pytest.mark.parametrize("siswap_op", [qml.SISWAP, qml.SQISW])
def test_siswap_eigenval(self, siswap_op):
"""Tests that the ISWAP eigenvalue matches the numpy eigenvalues of the ISWAP matrix"""
op = siswap_op(wires=[0, 1])
exp = np.linalg.eigvals(op.matrix)
res = op.eigvals
assert np.allclose(res, exp)

def test_swap_decomposition(self):
"""Tests the swap operator produces the correct output"""
opr = qml.SWAP(wires=[0, 1])
Expand Down