Skip to content

Commit

Permalink
set the default state prep label to a psi ket (#4340)
Browse files Browse the repository at this point in the history
* set the default state prep label to a psi ket

* Update doc/releases/changelog-dev.md

Co-authored-by: Mudit Pandey <mudit.pandey@xanadu.ai>

* fix tests

* do not test matrix for stateprep op labels

* lint test_operation.py

* fix pylint disable

* Update doc/releases/changelog-dev.md

Co-authored-by: Christina Lee <christina@xanadu.ai>

---------

Co-authored-by: Mudit Pandey <mudit.pandey@xanadu.ai>
Co-authored-by: Christina Lee <christina@xanadu.ai>
  • Loading branch information
3 people authored Jul 12, 2023
1 parent 716b4b9 commit 97c7272
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 52 deletions.
3 changes: 3 additions & 0 deletions doc/releases/changelog-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
* QNode transforms in `qml.qinfo` now support custom wire labels.
[#4331](https://github.com/PennyLaneAI/pennylane/pull/4331)

* The default label for a `StatePrep` operator is now `|Ψ⟩`.
[(#4340)](https://github.com/PennyLaneAI/pennylane/pull/4340)

<h3>Breaking changes 💔</h3>

* The `do_queue` keyword argument in `qml.operation.Operator` has been removed. Instead of
Expand Down
3 changes: 3 additions & 0 deletions pennylane/operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -2706,6 +2706,9 @@ def state_vector(self, wire_order=None):
array: A state vector for all wires in a circuit
"""

def label(self, decimals=None, base_label=None, cache=None):
return "|Ψ⟩"


def operation_derivative(operation) -> np.ndarray:
r"""Calculate the derivative of an operation.
Expand Down
31 changes: 13 additions & 18 deletions tests/drawer/test_draw.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,18 +166,14 @@ def matrices_circuit():
qml.QubitUnitary(np.eye(2), wires=0)
return qml.expval(qml.Hermitian(np.eye(2), wires=0))

expected1 = (
"0: ─╭QubitStateVector(M0)──U(M1)─┤ <𝓗(M1)>\n"
"1: ─╰QubitStateVector(M0)────────┤ "
)
expected1 = "0: ─╭|Ψ⟩──U(M0)─┤ <𝓗(M0)>\n1: ─╰|Ψ⟩────────┤ "

assert draw(matrices_circuit, show_matrices=False)() == expected1

expected2 = (
"0: ─╭QubitStateVector(M0)──U(M1)─┤ <𝓗(M1)>\n"
"1: ─╰QubitStateVector(M0)────────┤ \n"
"M0 = \n[1. 0. 0. 0.]\n"
"M1 = \n[[1. 0.]\n [0. 1.]]"
"0: ─╭|Ψ⟩──U(M0)─┤ <𝓗(M0)>\n"
"1: ─╰|Ψ⟩────────┤ \n"
"M0 = \n[[1. 0.]\n [0. 1.]]"
)

assert draw(matrices_circuit)() == expected2
Expand All @@ -194,21 +190,20 @@ def matrices_circuit(x):
return qml.expval(qml.Hermitian(np.eye(2, requires_grad=False), wires=1))

expected1 = (
"0: ─╭QubitStateVector(M0)──U(M1)────┤ \n"
"1: ─╰QubitStateVector(M0)──RX(1.20)─┤ <𝓗(M1)>\n\n"
"0: ─╭QubitStateVector(M0)──U(M1)────┤ \n"
"1: ─╰QubitStateVector(M0)──RX(0.80)─┤ <𝓗(M1)>\n\n"
"M0 = \n[1. 0. 0. 0.]\n"
"M1 = \n[[1. 0.]\n [0. 1.]]"
"0: ─╭|Ψ⟩──U(M0)────┤ \n"
"1: ─╰|Ψ⟩──RX(1.20)─┤ <𝓗(M0)>\n\n"
"0: ─╭|Ψ⟩──U(M0)────┤ \n"
"1: ─╰|Ψ⟩──RX(0.80)─┤ <𝓗(M0)>\n\n"
"M0 = \n[[1. 0.]\n [0. 1.]]"
)
output = draw(matrices_circuit)(np.array(1.0, requires_grad=True))
assert output == expected1

expected2 = (
"0: ─╭QubitStateVector(M0)──U(M1)────┤ \n"
"1: ─╰QubitStateVector(M0)──RX(1.20)─┤ <𝓗(M1)>\n\n"
"0: ─╭QubitStateVector(M0)──U(M1)────┤ \n"
"1: ─╰QubitStateVector(M0)──RX(0.80)─┤ <𝓗(M1)>"
"0: ─╭|Ψ⟩──U(M0)────┤ \n"
"1: ─╰|Ψ⟩──RX(1.20)─┤ <𝓗(M0)>\n\n"
"0: ─╭|Ψ⟩──U(M0)────┤ \n"
"1: ─╰|Ψ⟩──RX(0.80)─┤ <𝓗(M0)>"
)
output = draw(matrices_circuit, show_matrices=False)(np.array(1.0, requires_grad=True))
assert output == expected2
Expand Down
22 changes: 8 additions & 14 deletions tests/drawer/test_tape_text.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ def test_setting_max_length(self, ml):
(qml.AmplitudeDamping(0.98, wires=0), "0: ──AmplitudeDamping(0.98)─┤ "),
(
qml.QubitStateVector([0, 1, 0, 0], wires=(0, 1)),
"0: ─╭QubitStateVector(M0)─┤ \n1: ─╰QubitStateVector(M0)─┤ ",
"0: ─╭|Ψ⟩─┤ \n1: ─╰|Ψ⟩─┤ ",
),
(qml.Kerr(1.234, wires=0), "0: ──Kerr(1.23)─┤ "),
(
Expand Down Expand Up @@ -396,21 +396,17 @@ def test_default_shows_matrix_parameters(self):
"""Test matrices numbered but not included by default."""

expected = (
"0: ─╭QubitStateVector(M0)──U(M1)─┤ <𝓗(M1)>\n"
"1: ─╰QubitStateVector(M0)────────┤ \n"
"M0 = \n[1. 0. 0. 0.]\n"
"M1 = \n[[1. 0.]\n [0. 1.]]"
"0: ─╭|Ψ⟩──U(M0)─┤ <𝓗(M0)>\n"
"1: ─╰|Ψ⟩────────┤ \n"
"M0 = \n[[1. 0.]\n [0. 1.]]"
)

assert tape_text(tape_matrices) == expected

def test_do_not_show_matrices(self):
"""Test matrices included when requested."""

expected = (
"0: ─╭QubitStateVector(M0)──U(M1)─┤ <𝓗(M1)>\n"
"1: ─╰QubitStateVector(M0)────────┤ "
)
expected = "0: ─╭|Ψ⟩──U(M0)─┤ <𝓗(M0)>\n1: ─╰|Ψ⟩────────┤ "

assert tape_text(tape_matrices, show_matrices=False) == expected

Expand All @@ -421,15 +417,13 @@ def test_matrix_parameters_provided_cache(self):
cache = {"matrices": [np.eye(2), -np.eye(3)]}

expected = (
"0: ─╭QubitStateVector(M2)──U(M0)─┤ <𝓗(M0)>\n"
"1: ─╰QubitStateVector(M2)────────┤ \n"
"0: ─╭|Ψ⟩──U(M0)─┤ <𝓗(M0)>\n"
"1: ─╰|Ψ⟩────────┤ \n"
"M0 = \n[[1. 0.]\n [0. 1.]]\n"
"M1 = \n[[-1. -0. -0.]\n [-0. -1. -0.]\n [-0. -0. -1.]]\n"
"M2 = \n[1. 0. 0. 0.]"
"M1 = \n[[-1. -0. -0.]\n [-0. -1. -0.]\n [-0. -0. -1.]]"
)

assert tape_text(tape_matrices, show_matrices=True, cache=cache) == expected
assert qml.math.allequal(cache["matrices"][2], [1.0, 0.0, 0.0, 0.0])


# @pytest.mark.skip("Nested tapes are being deprecated")
Expand Down
2 changes: 0 additions & 2 deletions tests/ops/qubit/test_state_prep.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ def test_adjoint_error_exception(op):
@pytest.mark.parametrize(
"op, mat, base",
[
(qml.BasisState(np.array([0, 1]), wires=0), [0, 1], "BasisState"),
(qml.QubitStateVector(np.array([1.0, 0.0]), wires=0), [1.0, 0.0], "QubitStateVector"),
(qml.QubitDensityMatrix(densitymat0, wires=0), densitymat0, "QubitDensityMatrix"),
],
)
Expand Down
38 changes: 20 additions & 18 deletions tests/test_operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ class MyOp(qml.operation.Operation):
class MyOpOverwriteInit(qml.operation.Operation):
num_wires = 1

def __init__(self, wires):
def __init__(self, wires): # pylint:disable=super-init-not-called
pass

op = MyOp(wires=0)
Expand All @@ -266,7 +266,7 @@ def test_custom_hyperparams(self):
class MyOp(qml.operation.Operation):
num_wires = 1

def __init__(self, wires, basis_state=None):
def __init__(self, wires, basis_state=None): # pylint:disable=super-init-not-called
self._hyperparameters = {"basis_state": basis_state}

state = [0, 1, 0]
Expand Down Expand Up @@ -417,7 +417,7 @@ class MyOp(qml.operation.Operator):
num_wires = 1

@staticmethod
def compute_matrix():
def compute_matrix(*params, **hyperparams):
return np.eye(2)

assert MyOp.has_matrix is True
Expand Down Expand Up @@ -469,7 +469,7 @@ class MyOp(qml.operation.Operator):
num_params = 1

@staticmethod
def compute_decomposition(x, wires=None):
def compute_decomposition(x, wires=None): # pylint:disable=arguments-differ
return [qml.RX(x, wires=wires)]

assert MyOp.has_decomposition is True
Expand Down Expand Up @@ -507,7 +507,7 @@ class MyOp(qml.operation.Operator):
num_params = 1

@staticmethod
def compute_diagonalizing_gates(x, wires=None):
def compute_diagonalizing_gates(x, wires=None): # pylint:disable=arguments-differ
return []

assert MyOp.has_diagonalizing_gates is True
Expand Down Expand Up @@ -2082,7 +2082,7 @@ class MyOpWithMat(Operator):
num_wires = 1

@staticmethod
def compute_matrix(theta):
def compute_matrix(theta): # pylint:disable=arguments-differ
return np.tensordot(theta, np.array([[0.4, 1.2], [1.2, 0.4]]), axes=0)


Expand Down Expand Up @@ -2117,7 +2117,7 @@ class DummyOp(qml.operation.Channel):
grad_method = "F"

@staticmethod
def compute_kraus_matrices(p):
def compute_kraus_matrices(p): # pylint:disable=arguments-differ
K1 = np.sqrt(p) * X
K2 = np.sqrt(1 - p) * I
return [K1, K2]
Expand Down Expand Up @@ -2258,19 +2258,17 @@ class DummyOp(qml.operation.CVOperation):
class TestStatePrep:
"""Test the StatePrep interface."""

class DefaultPrep(StatePrep):
"""A dummy class that assumes it was given a state vector."""

# pylint:disable=unused-argument,too-few-public-methods
def state_vector(self, wire_order=None):
return self.parameters[0]

# pylint:disable=unused-argument,too-few-public-methods
def test_basic_stateprep(self):
"""Tests a basic implementation of the StatePrep interface."""

class DefaultPrep(StatePrep):
"""A dummy class that assumes it was given a state vector."""

num_wires = qml.operation.AllWires

def state_vector(self, wire_order=None):
return self.parameters[0]

prep_op = DefaultPrep([1, 0], wires=[0])
prep_op = self.DefaultPrep([1, 0], wires=[0])
assert np.array_equal(prep_op.state_vector(), [1, 0])

def test_child_must_implement_state_vector(self):
Expand All @@ -2279,11 +2277,15 @@ def test_child_must_implement_state_vector(self):
class NoStatePrepOp(StatePrep):
"""A class that is missing the state_vector implementation."""

num_wires = qml.operation.AllWires
# pylint:disable=abstract-class-instantiated

with pytest.raises(TypeError, match="Can't instantiate abstract class"):
NoStatePrepOp(wires=[0])

def test_StatePrep_label(self):
"""Tests that StatePrep classes by default have a psi ket label"""
assert self.DefaultPrep([1], 0).label() == "|Ψ⟩"


class TestCriteria:
doubleExcitation = qml.DoubleExcitation(0.1, wires=[0, 1, 2, 3])
Expand Down

0 comments on commit 97c7272

Please sign in to comment.