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

Remove complex warning from operator matrices #1802

Merged
merged 11 commits into from
Oct 27, 2021
7 changes: 6 additions & 1 deletion pennylane/devices/default_qubit.py
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,7 @@ def expval(self, observable, shot_range=None, bin_size=None):
# Compute <psi| H |psi> via sum_i coeff_i * <psi| PauliWord |psi> using a sparse
# representation of the Pauliword
res = qml.math.cast(qml.math.convert_like(0.0, observable.data), dtype=complex)
interface = qml.math.get_interface(self.state)

# Note: it is important that we use the Hamiltonian's data and not the coeffs attribute.
# This is because the .data attribute may be 'unwrapped' as required by the interfaces,
Expand All @@ -502,7 +503,11 @@ def expval(self, observable, shot_range=None, bin_size=None):
* Hmat
* qml.math.gather(self.state, coo.col)
)
c = qml.math.cast(qml.math.convert_like(coeff, product), "complex128")
c = qml.math.convert_like(coeff, product)

if interface == "tensorflow":
c = qml.math.cast(c, "complex128")
Comment on lines +508 to +509
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tracked down another complex warning here. @glassnotes, I fear more are hiding still 😆

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm very confused about this one, is it not doing the exact same thing but in two lines? Or does doing the casting in the other frameworks spit out a warning while tensorflow does not? 😕

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep! during the backwards pass, the reverse will happen - a complex value will be cast to real. Which... generates the warning in PyTorch and Autograd 🤦

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤦‍♀️ indeed


res = qml.math.convert_like(res, product) + qml.math.sum(c * product)

else:
Expand Down
55 changes: 28 additions & 27 deletions pennylane/ops/qubit/parametric_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ def _matrix(cls, *params):

js = -1j * s

return qml.math.stack([qml.math.stack([c, js]), qml.math.stack([js, c])])
return qml.math.diag([c, c]) + qml.math.stack(
[qml.math.stack([0, js]), qml.math.stack([js, 0])]
)

def adjoint(self):
return RX(-self.data[0], wires=self.wires)
Expand Down Expand Up @@ -122,7 +124,9 @@ def _matrix(cls, *params):
c = qml.math.cos(theta / 2)
s = qml.math.sin(theta / 2)

return qml.math.stack([qml.math.stack([c, -s]), qml.math.stack([s, c])])
return qml.math.diag([c, c]) + qml.math.stack(
[qml.math.stack([0, -s]), qml.math.stack([s, 0])]
)

def adjoint(self):
return RY(-self.data[0], wires=self.wires)
Expand Down Expand Up @@ -838,18 +842,23 @@ def label(self, decimals=None, base_label=None):
@classmethod
def _matrix(cls, *params):
theta = params[0]
interface = qml.math.get_interface(theta)

c = qml.math.cos(theta / 2)
s = qml.math.sin(theta / 2)
z = qml.math.zeros([4], like=interface)

if qml.math.get_interface(theta) == "tensorflow":
if interface == "tensorflow":
c = qml.math.cast_like(c, 1j)
s = qml.math.cast_like(s, 1j)
z = qml.math.cast_like(z, 1j)

js = -1j * s

mat = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, c, js], [0, 0, js, c]]
return qml.math.stack([qml.math.stack(row) for row in mat])
mat = qml.math.diag([1, 1, c, c])
return mat + qml.math.stack(
[z, z, qml.math.stack([0, 0, 0, js]), qml.math.stack([0, 0, js, 0])]
)

@staticmethod
def decomposition(theta, wires):
Expand Down Expand Up @@ -928,12 +937,16 @@ def label(self, decimals=None, base_label=None):
@classmethod
def _matrix(cls, *params):
theta = params[0]
interface = qml.math.get_interface(theta)

c = qml.math.cos(theta / 2)
s = qml.math.sin(theta / 2)
z = qml.math.zeros([4], like=interface)

mat = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, c, -s], [0, 0, s, c]]
return qml.math.stack([qml.math.stack(row) for row in mat])
mat = qml.math.diag([1, 1, c, c])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this necessary here, since CRY is purely real?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

weirdly yes, for the same reason that OrbitalRotation also raises the warning. I'm not entirely sure why this is an issue though?? So weird.

return mat + qml.math.stack(
[z, z, qml.math.stack([0, 0, 0, -s]), qml.math.stack([0, 0, s, 0])]
)

@staticmethod
def decomposition(theta, wires):
Expand Down Expand Up @@ -1396,20 +1409,15 @@ def _matrix(cls, *params):

c = qml.math.cos(phi / 2)
s = qml.math.sin(phi / 2)
Y = qml.math.convert_like(np.eye(4)[::-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)

js = -1j * s

mat = [
[c, 0, 0, js],
[0, c, js, 0],
[0, js, c, 0],
[js, 0, 0, c],
]

return qml.math.stack([qml.math.stack(row) for row in mat])
mat = qml.math.diag([c, c, c, c]) - 1j * s * Y
return mat

@staticmethod
def decomposition(phi, wires):
Expand Down Expand Up @@ -1471,21 +1479,14 @@ def _matrix(cls, *params):

c = qml.math.cos(phi / 2)
s = qml.math.sin(phi / 2)
Y = qml.math.convert_like(np.diag([1, -1, -1, 1])[::-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)

js = 1j * s

mat = [
[c, 0.0, 0.0, js],
[0.0, c, -js, 0.0],
[0.0, -js, c, 0.0],
[js, 0.0, 0.0, c],
]

return qml.math.stack([qml.math.stack(row) for row in mat])
return qml.math.diag([c, c, c, c]) + 1j * s * Y

def adjoint(self):
(phi,) = self.parameters
Expand Down
137 changes: 48 additions & 89 deletions pennylane/ops/qubit/qchem_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,9 @@ def _matrix(cls, *params):
c = qml.math.cos(theta / 2)
s = qml.math.sin(theta / 2)

mat = [[1, 0, 0, 0], [0, c, -s, 0], [0, s, c, 0], [0, 0, 0, 1]]
return qml.math.stack([qml.math.stack(row) for row in mat])
mat = qml.math.diag([1, c, c, 1])
off_diag = qml.math.convert_like(np.diag([0, 1, -1, 0])[::-1].copy(), theta)
return mat + s * qml.math.cast_like(off_diag, s)

@staticmethod
def decomposition(theta, wires):
Expand Down Expand Up @@ -163,9 +164,9 @@ def _matrix(cls, *params):
s = qml.math.cast_like(s, 1j)

e = qml.math.exp(-1j * theta / 2)

mat = [[e, 0, 0, 0], [0, c, -s, 0], [0, s, c, 0], [0, 0, 0, e]]
return qml.math.stack([qml.math.stack(row) for row in mat])
mat = qml.math.diag([e, 0, 0, e]) + qml.math.diag([0, c, c, 0])
off_diag = qml.math.convert_like(np.diag([0, 1, -1, 0])[::-1].copy(), theta)
return mat + s * qml.math.cast_like(off_diag, s)

@staticmethod
def decomposition(theta, wires):
Expand Down Expand Up @@ -238,9 +239,9 @@ def _matrix(cls, *params):
s = qml.math.cast_like(s, 1j)

e = qml.math.exp(1j * theta / 2)

mat = [[e, 0, 0, 0], [0, c, -s, 0], [0, s, c, 0], [0, 0, 0, e]]
return qml.math.stack([qml.math.stack(row) for row in mat])
mat = qml.math.diag([e, 0, 0, e]) + qml.math.diag([0, c, c, 0])
off_diag = qml.math.convert_like(np.diag([0, 1, -1, 0])[::-1].copy(), theta)
return mat + s * qml.math.cast_like(off_diag, s)

@staticmethod
def decomposition(theta, wires):
Expand Down Expand Up @@ -332,26 +333,10 @@ def _matrix(cls, *params):
c = qml.math.cos(theta / 2)
s = qml.math.sin(theta / 2)

mat = [
[1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, c, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -s, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, s, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, c, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0],
]

return qml.math.stack([qml.math.stack(row) for row in mat])
mat = qml.math.diag([1.0] * 3 + [c] + [1.0] * 8 + [c] + [1.0] * 3)
mat = qml.math.scatter_element_add(mat, (3, 12), -s)
mat = qml.math.scatter_element_add(mat, (12, 3), s)
return mat

@staticmethod
def decomposition(theta, wires):
Expand Down Expand Up @@ -454,26 +439,12 @@ def _matrix(cls, *params):

e = qml.math.exp(1j * theta / 2)

mat = [
[e, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, e, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, e, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, c, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -s, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, e, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, e, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, e, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, e, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, e, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, e, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, e, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, e, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, s, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, c, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, e, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, e, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, e],
]

return qml.math.stack([qml.math.stack(row) for row in mat])
mat = qml.math.diag([e] * 3 + [0] + [e] * 8 + [0] + [e] * 3)
mat = qml.math.scatter_element_add(mat, (3, 3), c)
mat = qml.math.scatter_element_add(mat, (3, 12), -s)
mat = qml.math.scatter_element_add(mat, (12, 3), s)
mat = qml.math.scatter_element_add(mat, (12, 12), c)
return mat

def adjoint(self):
(theta,) = self.parameters
Expand Down Expand Up @@ -539,27 +510,12 @@ def _matrix(cls, *params):
s = qml.math.cast_like(s, 1j)

e = qml.math.exp(-1j * theta / 2)

mat = [
[e, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, e, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, e, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, c, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -s, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, e, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, e, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, e, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, e, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, e, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, e, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, e, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, e, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, s, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, c, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, e, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, e, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, e],
]

return qml.math.stack([qml.math.stack(row) for row in mat])
mat = qml.math.diag([e] * 3 + [0] + [e] * 8 + [0] + [e] * 3)
mat = qml.math.scatter_element_add(mat, (3, 3), c)
mat = qml.math.scatter_element_add(mat, (3, 12), -s)
mat = qml.math.scatter_element_add(mat, (12, 3), s)
mat = qml.math.scatter_element_add(mat, (12, 12), c)
return mat

def adjoint(self):
(theta,) = self.parameters
Expand Down Expand Up @@ -657,30 +613,33 @@ def _matrix(cls, *params):
# Additionally, there was a typo in the sign of a matrix element "s" at [2, 8], which is fixed here.

phi = params[0]
interface = qml.math.get_interface(phi)
c = qml.math.cos(phi / 2)
s = qml.math.sin(phi / 2)
z = qml.math.zeros([16], like=interface)

matrix = [
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, c, 0, 0, -s, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, c, 0, 0, 0, 0, 0, -s, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, c ** 2, 0, 0, -c * s, 0, 0, -c * s, 0, 0, s ** 2, 0, 0, 0],
[0, s, 0, 0, c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, c * s, 0, 0, c ** 2, 0, 0, -(s ** 2), 0, 0, -c * s, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, c, 0, 0, 0, 0, 0, -s, 0, 0],
[0, 0, s, 0, 0, 0, 0, 0, c, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, c * s, 0, 0, -(s ** 2), 0, 0, c ** 2, 0, 0, -c * s, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, c, 0, 0, -s, 0],
[0, 0, 0, s ** 2, 0, 0, c * s, 0, 0, c * s, 0, 0, c ** 2, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, s, 0, 0, 0, 0, 0, c, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, s, 0, 0, c, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
]
diag = qml.math.diag([1, c, c, c ** 2, c, 1, c ** 2, c, c, c ** 2, 1, c, c ** 2, c, c, 1])

# first stack each row and then stack all the rows
U = qml.math.stack([qml.math.stack(row) for row in matrix], axis=0)
U = diag + qml.math.stack(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wait why does this fix it 🤯 what makes the diagonal part different???????????

This PR has made me so confused

Copy link
Member Author

@josh146 josh146 Oct 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

at some point in the future other devs are going to look at this and just be like why is the matrix coded like this hahahaha

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know, I'm just totally baffled! It's the exact same matrix! We can always leave a humorous warning for the next dev who looks at it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... which, realistically, is going to be us and @mariaschuld while doing the operator refactor.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@josh146 Hahaha, having a laugh reading through this, and finding myself in this statement:

at some point in the future other devs are going to look at this and just be like why is the matrix coded like this hahahaha

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In retrospect we should have added comments to the code, linking back to this PR for context to future developers 😆

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wait @dwierichs how did you find this PR

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wondering the same thing! 😂

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am going to implement batching for parametrized operations and therefore need to modify this code :D
The version I'm currently going with is

@staticmethod
def compute_matrix(theta):
    c = qml.math.cos(theta / 2)
    s = qml.math.sin(theta / 2)
    if qml.math.get_interface(theta)=="tensorflow":
        c = qml.math.cast_like(c, 1j)
        s = qml.math.cast_like(s, 1j)
    
    mat = qml.math.stack([qml.math.stack([c, s]), qml.math.stack([s, c])])
    return mat * qml.math.array([[1+0j, -1j], [-1j, 1+0j]], like=mat)

which is batch-compatible (i.e. theta being non-scalar) and also is 20% or so faster in the scalar case :)

[
z,
qml.math.stack([0, 0, 0, 0, -s, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]),
qml.math.stack([0, 0, 0, 0, 0, 0, 0, 0, -s, 0, 0, 0, 0, 0, 0, 0]),
qml.math.stack([0, 0, 0, 0, 0, 0, -c * s, 0, 0, -c * s, 0, 0, s * s, 0, 0, 0]),
qml.math.stack([0, s, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]),
z,
qml.math.stack([0, 0, 0, c * s, 0, 0, 0, 0, 0, -s * s, 0, 0, -c * s, 0, 0, 0]),
qml.math.stack([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -s, 0, 0]),
qml.math.stack([0, 0, s, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]),
qml.math.stack([0, 0, 0, c * s, 0, 0, -s * s, 0, 0, 0, 0, 0, -c * s, 0, 0, 0]),
z,
qml.math.stack([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -s, 0]),
qml.math.stack([0, 0, 0, s * s, 0, 0, c * s, 0, 0, c * s, 0, 0, 0, 0, 0, 0]),
qml.math.stack([0, 0, 0, 0, 0, 0, 0, s, 0, 0, 0, 0, 0, 0, 0, 0]),
qml.math.stack([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, s, 0, 0, 0, 0]),
z,
]
)

return U

Expand Down
2 changes: 1 addition & 1 deletion tests/ops/qubit/test_hamiltonian.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
try:
import torch

COEFFS_PARAM_INTERFACE.append((torch.tensor([-0.05, 0.17]), torch.tensor([1.7]), "torch"))
COEFFS_PARAM_INTERFACE.append((torch.tensor([-0.05, 0.17]), torch.tensor(1.7), "torch"))
josh146 marked this conversation as resolved.
Show resolved Hide resolved
except ImportError:
pass

Expand Down
2 changes: 1 addition & 1 deletion tests/ops/qubit/test_qchem_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -910,7 +910,7 @@ def circuit(phi):
qml.OrbitalRotation(phi, wires=[0, 1, 2, 3])
return qml.expval(qml.PauliZ(0))

phi_t = torch.tensor(phi, dtype=torch.float64, requires_grad=True)
phi_t = torch.tensor(phi, dtype=torch.complex128, requires_grad=True)

result = circuit(phi_t)
result.backward()
Expand Down