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 IsingXY [unitaryhack] #2649

Merged
merged 43 commits into from
Jun 7, 2022
Merged
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
4ae642a
Add IsingXY
ankit27kh May 25, 2022
280d974
add IsingXY gate data
ankit27kh May 25, 2022
3f3df9f
add isingxy
ankit27kh May 25, 2022
9f6acb1
add pow
ankit27kh May 25, 2022
f06b6c3
correct decomposition
ankit27kh May 25, 2022
84a5363
add test_isingxy_decomposition
ankit27kh May 25, 2022
95a083e
fix typo
ankit27kh May 25, 2022
22cb04c
add test_isingxy
ankit27kh May 25, 2022
6d3a37e
add pow and control test for xy
ankit27kh May 25, 2022
42f9619
add isingxy
ankit27kh May 25, 2022
619cf8b
add isingxy
ankit27kh May 25, 2022
c69cac1
add tests for isingxy
ankit27kh May 25, 2022
ae409ac
fix typo
ankit27kh May 25, 2022
86d25e3
add grad tests
ankit27kh May 25, 2022
e1e9e3c
add 2616
ankit27kh May 25, 2022
aaa6a74
Merge branch 'master' into patch-1
ankit27kh May 25, 2022
002c648
add name
ankit27kh May 26, 2022
e5c19a3
add compute_eigvals
ankit27kh May 26, 2022
300c491
Delete changelog-dev.md
ankit27kh May 28, 2022
bf76b7b
Add files via upload
ankit27kh May 28, 2022
8fedbae
Merge branch 'PennyLaneAI:master' into patch-1
ankit27kh May 28, 2022
66bcfa3
add eigvals tests
ankit27kh May 28, 2022
633c3ef
update
ankit27kh May 28, 2022
b4cf8ad
update
ankit27kh Jun 2, 2022
853facb
update
ankit27kh Jun 2, 2022
bdeb1a7
Merge branch 'master' into patch-1
ankit27kh Jun 2, 2022
1c16fa2
black
ankit27kh Jun 2, 2022
4c0a28f
Merge branch 'master' into add_isingxy
ankit27kh Jun 2, 2022
b03bb3f
fix typo
ankit27kh Jun 4, 2022
cdd0ba8
Merge branch 'master' into add_isingxy
ankit27kh Jun 4, 2022
a9e0ddd
fix typo
ankit27kh Jun 4, 2022
71e2a7e
update eigvals and its test
ankit27kh Jun 4, 2022
55288c7
update generator
ankit27kh Jun 4, 2022
aff25e2
update eigs test
ankit27kh Jun 4, 2022
4234143
update eigs test
ankit27kh Jun 4, 2022
13183b5
fix eigs test
ankit27kh Jun 4, 2022
af716bd
fix eigvals test
ankit27kh Jun 6, 2022
fff9391
Merge branch 'master' into add_isingxy
ankit27kh Jun 6, 2022
d4b133b
changelog
ankit27kh Jun 6, 2022
ddd335c
Merge branch 'master' into add_isingxy
ankit27kh Jun 7, 2022
80ea7dd
fix typo and comments
ankit27kh Jun 7, 2022
83c2fbe
Merge branch 'master' into add_isingxy
ankit27kh Jun 7, 2022
9107ef5
Trigger CI
ankit27kh Jun 7, 2022
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
1 change: 1 addition & 0 deletions doc/introduction/operations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ Parametrized gates
~pennylane.U2
~pennylane.U3
~pennylane.IsingXX
~pennylane.IsingXY
~pennylane.IsingYY
~pennylane.IsingZZ

Expand Down
7 changes: 5 additions & 2 deletions doc/releases/changelog-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,9 @@
* Added separate requirements_dev.txt for separation of concerns for code development and just using PennyLane.
[(#2635)](https://github.com/PennyLaneAI/pennylane/pull/2635)

* Add `IsingXY` gate.
[(#2649)](https://github.com/PennyLaneAI/pennylane/pull/2649)

<h3>Breaking changes</h3>

* The `qml.queuing.Queue` class is now removed.
Expand Down Expand Up @@ -389,6 +392,6 @@

This release contains contributions from (in alphabetical order):

Amintor Dusko, Chae-Yeun Park, Christian Gogolin, Christina Lee, David Wierichs, Edward Jiang, Guillermo Alonso-Linaje,
Amintor Dusko, Ankit Khandelwal, Chae-Yeun Park, Christian Gogolin, Christina Lee, David Wierichs, Edward Jiang, Guillermo Alonso-Linaje,
Jay Soni, Juan Miguel Arrazola, Korbinian, Kottmann, Maria Schuld, Mikhail Andrenkov, Romain Moyard, Qi Hu, Samuel Banning, Soran Jahangiri,
Utkarsh Azad, WingCode
Utkarsh Azad, WingCode
1 change: 1 addition & 0 deletions pennylane/devices/default_qubit.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ class DefaultQubit(QubitDevice):
"IsingXX",
"IsingYY",
"IsingZZ",
"IsingXY",
"SingleExcitation",
"SingleExcitationPlus",
"SingleExcitationMinus",
Expand Down
11 changes: 11 additions & 0 deletions pennylane/devices/tests/test_gates.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
"IsingXX": qml.IsingXX(0, wires=[0, 1]),
"IsingYY": qml.IsingYY(0, wires=[0, 1]),
"IsingZZ": qml.IsingZZ(0, wires=[0, 1]),
"IsingXY": qml.IsingXY(0, wires=[0, 1]),
"SingleExcitation": qml.SingleExcitation(0, wires=[0, 1]),
"SingleExcitationPlus": qml.SingleExcitationPlus(0, wires=[0, 1]),
"SingleExcitationMinus": qml.SingleExcitationMinus(0, wires=[0, 1]),
Expand Down Expand Up @@ -192,6 +193,15 @@
]
)

IsingXY = lambda phi: np.array(
[
[1, 0, 0, 0],
[0, cos(phi / 2), 1j * sin(phi / 2), 0],
[0, 1j * sin(phi / 2), cos(phi / 2), 0],
[0, 0, 0, 1],
]
)

IsingYY = lambda phi: np.array(
[
[cos(phi / 2), 0, 0, 1j * sin(phi / 2)],
Expand Down Expand Up @@ -255,6 +265,7 @@ def adjoint_tuple(op, orig_mat):
(qml.CRY, cry),
(qml.CRZ, crz),
(qml.IsingXX, IsingXX),
(qml.IsingXY, IsingXY),
(qml.IsingYY, IsingYY),
(qml.IsingZZ, IsingZZ),
]
Expand Down
1 change: 1 addition & 0 deletions pennylane/ops/qubit/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
"IsingXX",
"IsingYY",
"IsingZZ",
"IsingXY",
"BasisState",
"QubitStateVector",
"QubitDensityMatrix",
Expand Down
159 changes: 159 additions & 0 deletions pennylane/ops/qubit/parametric_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -2699,3 +2699,162 @@ def adjoint(self):

def pow(self, z):
return [IsingZZ(self.data[0] * z, wires=self.wires)]


class IsingXY(Operation):
r"""
Ising XY coupling gate

.. math:: \mathtt{XY}(\phi) = \begin{bmatrix}
1 & 0 & 0 & 0 \\
0 & \cos(\phi / 2) & i \sin(\phi / 2) & 0 \\
0 & i \sin(\phi / 2) & \cos(\phi / 2) & 0 \\
0 & 0 & 0 & 1
\end{bmatrix}.

**Details:**

* Number of wires: 2
* Number of parameters: 1
* Gradient recipe: The XY operator satisfies a four-term parameter-shift rule

.. math::
\frac{d}{d \phi} f(XY(\phi))
= c_+ \left[ f(XY(\phi + a)) - f(XY(\phi - a)) \right]
- c_- \left[ f(XY(\phi + b)) - f(XY(\phi - b)) \right]

where :math:`f` is an expectation value depending on :math:`XY(\phi)`, and

- :math:`a = \pi / 2`
- :math:`b = 3 \pi / 2`
- :math:`c_{\pm} = (\sqrt{2} \pm 1)/{4 \sqrt{2}}`

Args:
phi (float): the phase angle
wires (int): the subsystem the gate acts on
do_queue (bool): Indicates whether the operator should be
immediately pushed into the Operator queue (optional)
id (str or None): String representing the operation (optional)
"""
num_wires = 2
num_params = 1
"""int: Number of trainable parameters that the operator depends on."""

grad_method = "A"
parameter_frequencies = [(0.5, 1.0)]

def generator(self):
return 0.25 * qml.PauliX(wires=self.wires[0]) @ qml.PauliX(
wires=self.wires[1]
) + 0.25 * qml.PauliY(wires=self.wires[0]) @ qml.PauliY(wires=self.wires[1])

def __init__(self, phi, wires, do_queue=True, id=None):
super().__init__(phi, wires=wires, do_queue=do_queue, id=id)

@staticmethod
def compute_decomposition(phi, wires):
r"""Representation of the operator as a product of other operators (static method). :

.. math:: O = O_1 O_2 \dots O_n.


.. seealso:: :meth:`~.IsingXY.decomposition`.

Args:
phi (float): the phase angle
wires (Iterable, Wires): the subsystem the gate acts on

Returns:
list[Operator]: decomposition into lower level operations

**Example:**

>>> qml.IsingXY.compute_decomposition(1.23, wires=(0,1))
[Hadamard(wires=[0]), CY(wires=[0, 1]), RY(0.615, wires=[0]), RX(-0.615, wires=[1]), CY(wires=[0, 1]), Hadamard(wires=[0])]

"""
return [
qml.Hadamard(wires=[wires[0]]),
qml.CY(wires=wires),
qml.RY(phi / 2, wires=[wires[0]]),
qml.RX(-phi / 2, wires=[wires[1]]),
qml.CY(wires=wires),
qml.Hadamard(wires=[wires[0]]),
]

@staticmethod
def compute_matrix(phi): # pylint: disable=arguments-differ
r"""Representation of the operator as a canonical matrix in the computational basis (static method).

The canonical matrix is the textbook matrix representation that does not consider wires.
Implicitly, this assumes that the wires of the operator correspond to the global wire order.

.. seealso:: :meth:`~.IsingXY.matrix`


Args:
phi (tensor_like or float): phase angle

Returns:
tensor_like: canonical matrix

**Example**

>>> qml.IsingXY.compute_matrix(0.5)
array([[1. +0.j , 0. +0.j , 0. +0.j , 0. +0.j ],
[0. +0.j , 0.96891242+0.j , 0. +0.24740396j, 0. +0.j ],
[0. +0.j , 0. +0.24740396j, 0.96891242+0.j , 0. +0.j ],
[0. +0.j , 0. +0.j , 0. +0.j , 1. +0.j ]])
"""
c = qml.math.cos(phi / 2)
s = qml.math.sin(phi / 2)
Y = qml.math.convert_like(np.diag([0, 1, 1, 0])[::-1].copy(), phi)

if qml.math.get_interface(phi) == "tensorflow":
c = qml.math.cast_like(c, 1j)
s = qml.math.cast_like(s, 1j)
Y = qml.math.cast_like(Y, 1j)

return qml.math.diag([1, c, c, 1]) + 1j * s * Y

@staticmethod
def compute_eigvals(phi): # pylint: disable=arguments-differ
r"""Eigenvalues of the operator in the computational basis (static method).

If :attr:`diagonalizing_gates` are specified and implement a unitary :math:`U`,
the operator can be reconstructed as

.. math:: O = U \Sigma U^{\dagger},

where :math:`\Sigma` is the diagonal matrix containing the eigenvalues.

Otherwise, no particular order for the eigenvalues is guaranteed.

.. seealso:: :meth:`~.IsingXY.eigvals`


Args:
phi (tensor_like or float): phase angle

Returns:
tensor_like: eigenvalues

**Example**

>>> qml.IsingXY.compute_eigvals(0.5)
array([0.96891242+0.24740396j, 0.96891242-0.24740396j, 1. +0.j , 1. +0.j ])
"""
if qml.math.get_interface(phi) == "tensorflow":
phi = qml.math.cast_like(phi, 1j)
rmoyard marked this conversation as resolved.
Show resolved Hide resolved

pos_phase = qml.math.exp(1.0j * phi / 2)
neg_phase = qml.math.exp(-1.0j * phi / 2)

return qml.math.stack([pos_phase, neg_phase, 1, 1])

def adjoint(self):
(phi,) = self.parameters
return IsingXY(-phi, wires=self.wires)

def pow(self, z):
return [IsingXY(self.data[0] * z, wires=self.wires)]
23 changes: 23 additions & 0 deletions tests/gate_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,29 @@ def IsingYY(phi):
return np.cos(phi / 2) * II - 1j * np.sin(phi / 2) * YY


def IsingXY(phi):
r"""Ising XY coupling gate.

.. math:: \mathtt{XY}(\phi) = \begin{bmatrix}
1 & 0 & 0 & 0 \\
0 & \cos(\phi / 2) & i \sin(\phi / 2) & 0 \\
0 & i \sin(\phi / 2) & \cos(\phi / 2) & 0 \\
0 & 0 & 0 & 1
\end{bmatrix}.

Args:
phi (float): rotation angle :math:`\phi`
Returns:
array[complex]: unitary 4x4 rotation matrix
"""
mat = II.copy()
mat[1][1] = np.cos(phi / 2)
mat[2][2] = np.cos(phi / 2)
mat[1][2] = 1j * np.sin(phi / 2)
mat[2][1] = 1j * np.sin(phi / 2)
return mat


def IsingZZ(phi):
r"""Ising ZZ coupling gate

Expand Down
Loading