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

Change wire repr #5958

Merged
merged 12 commits into from
Jul 12, 2024
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
4 changes: 2 additions & 2 deletions doc/development/adding_operators.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ The basic components of operators are the following:
#. **The subsystems that the operator addresses** (:attr:`.Operator.wires`), which mathematically speaking defines the subspace that it acts on.

>>> op.wires
<Wires = ['a']>
Wires(['a'])

#. **Trainable parameters** (:attr:`.Operator.parameters`) that the map depends on, such as a rotation angle,
which can be fed to the operator as tensor-like objects. For example, since we used jax arrays to
Expand Down Expand Up @@ -237,7 +237,7 @@ If the above operator omitted the ``_unflatten`` custom definition, it would rai
The above exception was the direct cause of the following exception:

AssertionError: FlipAndRotate._unflatten must be able to reproduce the original operation
from (0.1,) and (<Wires = ['q3', 'q1']>, (('do_flip', True),)). You may need to override
from (0.1,) and (Wires(['q3', 'q1']), (('do_flip', True),)). You may need to override
either the _unflatten or _flatten method.
For local testing, try type(op)._unflatten(*op._flatten())

Expand Down
2 changes: 1 addition & 1 deletion doc/development/guide/architecture.rst
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ Rot
>>> op.hyperparameters
{}
>>> op.wires
<Wires = ['a']>
Wires(['a'])

Operators can optionally define the transformation they implement via
symbolic or numerical representations. Here are two examples, and you find more
Expand Down
10 changes: 5 additions & 5 deletions doc/development/plugins.rst
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ For example:
from pennylane.wires import Wires

wires = Wires(['auxiliary', 0, 1])
print(wires[0]) # <Wires = ['auxiliary']>
print(wires[0]) # Wires(['auxiliary'])
print(wires.labels) # ('auxiliary', 0, 1)

As shown in the section on :doc:`/introduction/circuits`, a device can be created with custom wire labels:
Expand All @@ -351,10 +351,10 @@ object and store it in their ``wires`` attribute.

.. code-block:: python

print(dev.wires) # <Wires = ['q11', 'q12', 'q21', 'q22']>
print(dev.wires) # Wires(['q11', 'q12', 'q21', 'q22'])

op = Gate2(wires=['q21','q11'])
print(op.wires) # <Wires = ['q21', 'q11']>
print(op.wires) # Wires(['q21', 'q11'])

When the device applies operations, it needs to translate
``op.wires`` into wire labels that the backend "understands". This can be done with the
Expand All @@ -365,7 +365,7 @@ but changes the labels according to the ``wire_map`` attribute of the device whi

# inside the class defining 'my.device', which inherits from the base Device class
device_wires = self.map_wires(op.wires)
print(device_wires) # <Wires = [2, 0]>
print(device_wires) # Wires([2, 0])

By default, the map translates the custom labels ``'q11'``, ``'q12'``, ``'q21'``, ``'q22'`` to
consecutive integers ``0``, ``1``, ``2``, ``3``. If a device uses a different wire labeling,
Expand Down Expand Up @@ -527,4 +527,4 @@ Users can then import this operator directly from your plugin, and use it when d

If the custom operator is diagonal in the computational basis, it can be added to the
``diagonal_in_z_basis`` attribute in ``pennylane.ops.qubit.attributes``. Devices can use this
information to implement faster simulations.
information to implement faster simulations.
4 changes: 4 additions & 0 deletions doc/releases/changelog-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
* `QuantumScript.hash` is now cached, leading to performance improvements.
[(#5919)](https://github.com/PennyLaneAI/pennylane/pull/5919)

* The representation for `Wires` has now changed to be more copy-paste friendly.
[(#5958)](https://github.com/PennyLaneAI/pennylane/pull/5958)

* Observable validation for `default.qubit` is now based on execution mode (analytic vs. finite shots) and measurement type (sample measurement vs. state measurement).
[(#5890)](https://github.com/PennyLaneAI/pennylane/pull/5890)

Expand Down Expand Up @@ -61,6 +64,7 @@ Astral Cai,
Yushao Chen,
Pietropaolo Frisoni,
Christina Lee,
Austin Huang,
William Maxwell,
Vincent Michaud-Rioux,
Mudit Pandey,
Expand Down
2 changes: 1 addition & 1 deletion pennylane/_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ def define_wire_map(self, wires):

>>> dev = device('my.device', wires=['b', 'a'])
>>> dev.wire_map()
OrderedDict( [(<Wires = ['a']>, <Wires = [0]>), (<Wires = ['b']>, <Wires = [1]>)])
OrderedDict( [(Wires(['a']), Wires([0])), (Wires(['b']), Wires([1]))])
"""
consecutive_wires = Wires(range(self.num_wires))

Expand Down
2 changes: 1 addition & 1 deletion pennylane/_qubit_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,7 @@ def apply(self, operations, **kwargs):
>>> op.name # returns the operation name
"RX"
>>> op.wires # returns a Wires object representing the wires that the operation acts on
<Wires = [0]>
Wires([0])
>>> op.parameters # returns a list of parameters
[0.2]

Expand Down
10 changes: 5 additions & 5 deletions pennylane/operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -557,7 +557,7 @@ def circuit(angle):

>>> op = qml.PauliRot(1.2, "XY", wires=(0,1))
>>> op._flatten()
((1.2,), (<Wires = [0, 1]>, (('pauli_word', 'XY'),)))
((1.2,), (Wires([0, 1]), (('pauli_word', 'XY'),)))
>>> qml.PauliRot._unflatten(*op._flatten())
PauliRot(1.2, XY, wires=[0, 1])

Expand Down Expand Up @@ -1629,7 +1629,7 @@ def _flatten(self):
>>> op = qml.ctrl(qml.U2(3.4, 4.5, wires="a"), ("b", "c") )
>>> op._flatten()
((U2(3.4, 4.5, wires=['a']),),
(<Wires = ['b', 'c']>, (True, True), <Wires = []>))
(Wires(['b', 'c']), (True, True), Wires([])))

"""
hashable_hyperparameters = tuple(
Expand All @@ -1652,11 +1652,11 @@ def _unflatten(cls, data, metadata):

>>> op = qml.Rot(1.2, 2.3, 3.4, wires=0)
>>> op._flatten()
((1.2, 2.3, 3.4), (<Wires = [0]>, ()))
((1.2, 2.3, 3.4), (Wires([0]), ()))
>>> qml.Rot._unflatten(*op._flatten())
>>> op = qml.PauliRot(1.2, "XY", wires=(0,1))
>>> op._flatten()
((1.2,), (<Wires = [0, 1]>, (('pauli_word', 'XY'),)))
((1.2,), (Wires([0, 1]), (('pauli_word', 'XY'),)))
>>> op = qml.ctrl(qml.U2(3.4, 4.5, wires="a"), ("b", "c") )
>>> type(op)._unflatten(*op._flatten())
Controlled(U2(3.4, 4.5, wires=['a']), control_wires=['b', 'c'])
Expand Down Expand Up @@ -1968,7 +1968,7 @@ def _obs_data(self):

>>> tensor = qml.X(0) @ qml.Z(1)
>>> print(tensor._obs_data())
{("PauliZ", <Wires = [1]>, ()), ("PauliX", <Wires = [0]>, ())}
{("PauliZ", Wires([1]), ()), ("PauliX", Wires([0]), ())}
"""
obs = Tensor(self).non_identity_obs
tensor = set()
Expand Down
6 changes: 3 additions & 3 deletions pennylane/ops/op_math/controlled.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,11 +322,11 @@ class Controlled(SymbolicOp):
>>> op.data
(1.234,)
>>> op.wires
<Wires = [0, 1]>
Wires([0, 1])
>>> op.control_wires
<Wires = [0]>
Wires([0])
>>> op.target_wires
<Wires = [1]>
Wires([1])

Control values are lists of booleans, indicating whether or not to control on the
``0==False`` value or the ``1==True`` wire.
Expand Down
4 changes: 2 additions & 2 deletions pennylane/ops/qubit/hamiltonian.py
Original file line number Diff line number Diff line change
Expand Up @@ -662,8 +662,8 @@ def _obs_data(self):

>>> H = qml.Hamiltonian([1, 1], [qml.X(0) @ qml.X(1), qml.Z(0)])
>>> print(H._obs_data())
{(1, frozenset({('PauliX', <Wires = [1]>, ()), ('PauliX', <Wires = [0]>, ())})),
(1, frozenset({('PauliZ', <Wires = [0]>, ())}))}
{(1, frozenset({('PauliX', Wires([1]), ()), ('PauliX', Wires([0]), ())})),
(1, frozenset({('PauliZ', Wires([0]), ())}))}
"""
data = set()

Expand Down
4 changes: 2 additions & 2 deletions pennylane/pytrees/pytrees.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ class PyTreeStructure:
>>> op = qml.adjoint(qml.RX(0.1, 0))
>>> data, structure = qml.pytrees.flatten(op)
>>> structure
PyTree(AdjointOperation, (), [PyTree(RX, (<Wires = [0]>, ()), [Leaf])])
PyTree(AdjointOperation, (), [PyTree(RX, (Wires([0]), ()), [Leaf])])

A leaf is defined as just a ``PyTreeStructure`` with ``type_=None``.
"""
Expand Down Expand Up @@ -236,7 +236,7 @@ def flatten(obj: Any) -> tuple[list[Any], PyTreeStructure]:
[1.2, 2.3, 3.4]

>>> structure
<PyTree(AdjointOperation, (), (<PyTree(Rot, (<Wires = [0]>, ()), (Leaf, Leaf, Leaf))>,))>
<PyTree(AdjointOperation, (), (<PyTree(Rot, (Wires([0]), ()), (Leaf, Leaf, Leaf))>,))>
"""
flatten_fn = flatten_registrations.get(type(obj), None)
if flatten_fn is None:
Expand Down
10 changes: 5 additions & 5 deletions pennylane/qchem/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,23 +58,23 @@ def _process_wires(wires, n_wires=None):

>>> # consec int wires if no wires mapping provided, ie. identity map: 0<->0, 1<->1, 2<->2
>>> _process_wires(None, 3)
<Wires = [0, 1, 2]>
Wires([0, 1, 2])

>>> # List as mapping, qubit indices with wire label values: 0<->w0, 1<->w1, 2<->w2
>>> _process_wires(['w0','w1','w2'])
<Wires = ['w0', 'w1', 'w2']>
Wires(['w0', 'w1', 'w2'])

>>> # Wires as mapping, qubit indices with wire label values: 0<->w0, 1<->w1, 2<->w2
>>> _process_wires(Wires(['w0', 'w1', 'w2']))
<Wires = ['w0', 'w1', 'w2']>
Wires(['w0', 'w1', 'w2'])

>>> # Dict as partial mapping, int qubits keys to wire label values: 0->w0, 1 unchanged, 2->w2
>>> _process_wires({0:'w0',2:'w2'})
<Wires = ['w0', 1, 'w2']>
Wires(['w0', 1, 'w2'])

>>> # Dict as mapping, wires label keys to consec int qubit values: w2->2, w0->0, w1->1
>>> _process_wires({'w2':2, 'w0':0, 'w1':1})
<Wires = ['w0', 'w1', 'w2']>
Wires(['w0', 'w1', 'w2'])
"""

# infer from wires, or assume 1 if wires is not of accepted types.
Expand Down
2 changes: 1 addition & 1 deletion pennylane/qchem/openfermion_pyscf.py
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,7 @@ def dipole_of(
>>> coordinates = np.array([0.028, 0.054, 0.0, 0.986, 1.610, 0.0, 1.855, 0.002, 0.0])
>>> dipole_obs = dipole_of(symbols, coordinates, charge=1)
>>> print([(h.wires) for h in dipole_obs])
[<Wires = [0, 1, 2, 3, 4, 5]>, <Wires = [0, 1, 2, 3, 4, 5]>, <Wires = [0]>]
[Wires([0, 1, 2, 3, 4, 5]), Wires([0, 1, 2, 3, 4, 5]), Wires([0])]

>>> dipole_obs[0] # x-component of D
(
Expand Down
2 changes: 1 addition & 1 deletion pennylane/tape/tape.py
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ class QuantumTape(QuantumScript, AnnotatedQueue):
>>> tape.get_parameters()
[0.432, 0.543, 0.133]
>>> tape.wires
<Wires = [0, 'a']>
Wires([0, 'a'])
>>> tape.num_params
3

Expand Down
2 changes: 1 addition & 1 deletion pennylane/templates/subroutines/qubitization.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ def compute_decomposition(*_, **kwargs): # pylint: disable=arguments-differ
**Example:**

>>> print(qml.Qubitization.compute_decomposition(hamiltonian = 0.1 * qml.Z(0), control = 1))
[AmplitudeEmbedding(array([1., 0.]), wires=[1]), Select(ops=(Z(0),), control=<Wires = [1]>), Adjoint(AmplitudeEmbedding(array([1., 0.]), wires=[1])), Reflection(, wires=[0])]
[AmplitudeEmbedding(array([1., 0.]), wires=[1]), Select(ops=(Z(0),), control=Wires([1])), Adjoint(AmplitudeEmbedding(array([1., 0.]), wires=[1])), Reflection(, wires=[0])]

"""

Expand Down
6 changes: 3 additions & 3 deletions pennylane/templates/subroutines/trotter.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ def _flatten(self):
>>> op = qml.ctrl(qml.U2(3.4, 4.5, wires="a"), ("b", "c") )
>>> op._flatten()
((U2(3.4, 4.5, wires=['a']),),
(<Wires = ['b', 'c']>, (True, True), <Wires = []>))
(Wires(['b', 'c']), (True, True), Wires([])))
"""
hamiltonian = self.hyperparameters["base"]
time = self.data[-1]
Expand All @@ -399,11 +399,11 @@ def _unflatten(cls, data, metadata):

>>> op = qml.Rot(1.2, 2.3, 3.4, wires=0)
>>> op._flatten()
((1.2, 2.3, 3.4), (<Wires = [0]>, ()))
((1.2, 2.3, 3.4), (Wires([0]), ()))
>>> qml.Rot._unflatten(*op._flatten())
>>> op = qml.PauliRot(1.2, "XY", wires=(0,1))
>>> op._flatten()
((1.2,), (<Wires = [0, 1]>, (('pauli_word', 'XY'),)))
((1.2,), (Wires([0, 1]), (('pauli_word', 'XY'),)))
>>> op = qml.ctrl(qml.U2(3.4, 4.5, wires="a"), ("b", "c") )
>>> type(op)._unflatten(*op._flatten())
Controlled(U2(3.4, 4.5, wires=['a']), control_wires=['b', 'c'])
Expand Down
18 changes: 9 additions & 9 deletions pennylane/wires.py
austingmhuang marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ def __contains__(self, item):

def __repr__(self):
"""Method defining the string representation of this class."""
return f"<Wires = {list(self._labels)}>"
return f"Wires({list(self._labels)})"

def __eq__(self, other):
"""Method to support the '==' operator.
Expand Down Expand Up @@ -286,7 +286,7 @@ def map(self, wire_map):
>>> wires = Wires(['a', 'b', 'c'])
>>> wire_map = {'a': 4, 'b':2, 'c': 3}
>>> wires.map(wire_map)
<Wires = [4, 2, 3]>
Wires([4, 2, 3])
"""
# Make sure wire_map has `Wires` keys and values so that the `in` operator always works

Expand Down Expand Up @@ -322,17 +322,17 @@ def subset(self, indices, periodic_boundary=False):

>>> wires = Wires([4, 0, 1, 5, 6])
>>> wires.subset([2, 3, 0])
<Wires = [1, 5, 4]>
Wires([1, 5, 4])
>>> wires.subset(1)
<Wires = [0]>
Wires([0])

If ``periodic_boundary`` is True, the modulo of the number of wires of an index is used instead of an index,
so that ``wires.subset(i) == wires.subset(i % n_wires)`` where ``n_wires`` is the number of wires of this
object.

>>> wires = Wires([4, 0, 1, 5, 6])
>>> wires.subset([5, 1, 7], periodic_boundary=True)
<Wires = [4, 0, 1]>
Wires([4, 0, 1])

"""

Expand Down Expand Up @@ -389,9 +389,9 @@ def shared_wires(list_of_wires):
>>> wires2 = Wires([3, 0, 4])
>>> wires3 = Wires([4, 0])
>>> Wires.shared_wires([wires1, wires2, wires3])
<Wires = [4, 0]>
Wires([4, 0])
>>> Wires.shared_wires([wires2, wires1, wires3])
<Wires = [0, 4]>
Wires([0, 4])
"""

for wires in list_of_wires:
Expand Down Expand Up @@ -431,7 +431,7 @@ def all_wires(list_of_wires, sort=False):
>>> wires3 = Wires([5, 3])
>>> list_of_wires = [wires1, wires2, wires3]
>>> Wires.all_wires(list_of_wires)
<Wires = [4, 0, 1, 3, 5]>
Wires([4, 0, 1, 3, 5])
"""
converted_wires = (
wires if isinstance(wires, Wires) else Wires(wires) for wires in list_of_wires
Expand Down Expand Up @@ -463,7 +463,7 @@ def unique_wires(list_of_wires):
>>> wires2 = Wires([0, 2, 3])
>>> wires3 = Wires([5, 3])
>>> Wires.unique_wires([wires1, wires2, wires3])
<Wires = [4, 1, 2, 5]>
Wires([4, 1, 2, 5])
"""

for wires in list_of_wires:
Expand Down
4 changes: 2 additions & 2 deletions pennylane/workflow/return_types_spec.rst
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ or ``qml.state()``. In such a case, the measurement process instance should have
The shape of the result object may be dictated either by the device or the other operations present in the circuit.

>>> qml.probs().wires
<Wires = []>
Wires([])
>>> tape = qml.tape.QuantumScript([qml.S(0)], (qml.probs(),))
>>> qml.device('default.qubit').execute(tape)
array([1., 0.])
Expand Down Expand Up @@ -176,4 +176,4 @@ where each entry corresponds to the result for the corresponding tape.
>>> tape3 = qml.tape.QuantumScript([], [qml.expval(qml.Z(0)), qml.expval(qml.X(0))])
>>> batch = (tape1, tape2, tape3)
>>> qml.device('default.qubit').execute(batch)
(array([0.+0.j, 1.+0.j]), {'0': 50, '1': 50}, (1.0, 0.0))
(array([0.+0.j, 1.+0.j]), {'0': 50, '1': 50}, (1.0, 0.0))
2 changes: 1 addition & 1 deletion tests/measurements/test_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ def get_state(ket):

def test_wire_ordering_error(self):
"""Test that a wire order error is raised when unknown wires are given."""
with pytest.raises(WireError, match=r"Unexpected unique wires <Wires = \[0, 1, 2\]> found"):
with pytest.raises(WireError, match=r"Unexpected unique wires Wires\(\[0, 1, 2\]\) found"):
StateMP(wires=[0, 1]).process_state([1, 0], wire_order=Wires(2))

@pytest.mark.parametrize(
Expand Down
4 changes: 2 additions & 2 deletions tests/pytrees/test_pytrees.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ def test_structure_repr_str():
"""Test the repr of the structure class."""
op = qml.RX(0.1, wires=0)
_, structure = qml.pytrees.flatten(op)
expected = "PyTreeStructure(RX, (<Wires = [0]>, ()), [PyTreeStructure()])"
expected = "PyTreeStructure(RX, (Wires([0]), ()), [PyTreeStructure()])"
assert repr(structure) == expected
expected_str = "PyTree(RX, (<Wires = [0]>, ()), [Leaf])"
expected_str = "PyTree(RX, (Wires([0]), ()), [Leaf])"
assert str(structure) == expected_str


Expand Down
3 changes: 1 addition & 2 deletions tests/templates/test_subroutines/test_prepselprep.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@ def test_repr():

op = qml.PrepSelPrep(lcu, control)
assert (
repr(op)
== "PrepSelPrep(coeffs=(0.25, 0.75), ops=(Z(2), X(1) @ X(2)), control=<Wires = [0]>)"
repr(op) == "PrepSelPrep(coeffs=(0.25, 0.75), ops=(Z(2), X(1) @ X(2)), control=Wires([0]))"
)


Expand Down
2 changes: 1 addition & 1 deletion tests/templates/test_subroutines/test_qrom.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ def test_repr():
["1", "0", "0", "1"], control_wires=[0, 1], target_wires=[2], work_wires=[3], clean=True
)
res = op.__repr__()
expected = "QROM(control_wires=<Wires = [0, 1]>, target_wires=<Wires = [2]>, work_wires=<Wires = [3]>, clean=True)"
expected = "QROM(control_wires=Wires([0, 1]), target_wires=Wires([2]), work_wires=Wires([3]), clean=True)"
assert res == expected


Expand Down
2 changes: 1 addition & 1 deletion tests/templates/test_subroutines/test_select.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def test_repr():
control = [1]

op = qml.Select(ops, control)
assert repr(op) == "Select(ops=(X(0), Y(0)), control=<Wires = [1]>)"
assert repr(op) == "Select(ops=(X(0), Y(0)), control=Wires([1]))"


class TestSelect:
Expand Down
Loading
Loading