From e844f15e1c7192a6ddffc159f51a6e1e0296a0fd Mon Sep 17 00:00:00 2001 From: EmilianoG-byte Date: Wed, 10 Jul 2024 16:46:49 -0400 Subject: [PATCH 01/14] change default value of measurements in from_qasm, improve documentation and examples --- pennylane/io.py | 147 ++++++++++++++++++++++++++--------------------- tests/test_io.py | 10 ---- 2 files changed, 81 insertions(+), 76 deletions(-) diff --git a/pennylane/io.py b/pennylane/io.py index dcf6ff6039e..351e5c73bb4 100644 --- a/pennylane/io.py +++ b/pennylane/io.py @@ -15,13 +15,10 @@ This module contains functions to load circuits from other frameworks as PennyLane templates. """ -import warnings from collections import defaultdict from importlib import metadata from sys import version_info -import pennylane as qml - # Error message to show when the PennyLane-Qiskit plugin is required but missing. _MISSING_QISKIT_PLUGIN_MESSAGE = ( "Conversion from Qiskit requires the PennyLane-Qiskit plugin. " @@ -410,96 +407,124 @@ def from_qiskit_op(qiskit_op, params=None, wires=None): raise RuntimeError(_MISSING_QISKIT_PLUGIN_MESSAGE) from e -def from_qasm(quantum_circuit: str, measurements=False): - """Loads quantum circuits from a QASM string using the converter in the +def from_qasm(quantum_circuit: str, measurements=None): + """ + Loads quantum circuits from a QASM string using the converter in the PennyLane-Qiskit plugin. Args: quantum_circuit (str): a QASM string containing a valid quantum circuit measurements (None | MeasurementProcess | list[MeasurementProcess]): an optional PennyLane measurement or list of PennyLane measurements that overrides any terminal measurements - that may be present in the input circuit. If set to ``None``, existing measurements - in the input circuit will be used. + that may be present in the input circuit. Defaults to ``None``, such that existing measurements + in the input circuit are kept. Returns: - function: the PennyLane template created based on the QASM string + function: the PennyLane quantum function created based on the QASM string. This function itself returns the mid-circuit measurements plus the terminal measurements by default (``measurements=None``), and returns the ``measurements`` otherwise. - By default, ``from_qasm`` will remove any measurements that are present in the QASM code. - If the QASM code contains measurements, set ``measurements=None`` to keep them in the - output of ``from_qasm``. + **Example:** - .. warning:: + .. code-block:: python - The current default behaviour of removing measurements in the QASM code is deprecated - and will be changed in a future release. Starting in version ``0.38``, ``from_qasm`` - will keep the measurements from the QASM code by default. To remove all measurements, - set ``measurements=[]`` which overrides the existing measurements with an empty list. + qasm_code = 'OPENQASM 2.0;'\\ + 'include "qelib1.inc";'\\ + 'qreg q[2];'\\ + 'creg c[2];'\\ + 'h q[0];'\\ + 'measure q[0] -> c[0];'\\ + 'rz(0.24) q[0];'\\ + 'cx q[0], q[1];'\\ + 'measure q -> c;' - **Example:** + loaded_circuit = qml.from_qasm(qasm_code) + + >>> print(qml.draw(loaded_circuit)()) + 0: ──H──┤↗├──RZ(0.24)─╭●──┤↗├─┤ + 1: ───────────────────╰X──┤↗├─┤ + + Calling the quantum function returns a tuple containing the mid-circuit measurements and the terminal measurements. + + >>> my_circuit() + (MeasurementValue(wires=[0]), + MeasurementValue(wires=[0]), + MeasurementValue(wires=[1])) + + To remove all terminal measurements, set ``measurements=[]`` which removes the existing terminal measurements, while keeping the mid circuit measurements. .. code-block:: python - >>> hadamard_qasm = 'OPENQASM 2.0;' \\ - ... 'include "qelib1.inc";' \\ - ... 'qreg q[1];' \\ - ... 'creg c[1];' \\ - ... 'h q[0];' - >>> my_circuit = qml.from_qasm(hadamard_qasm) - >>> my_circuit() - [] + loaded_circuit = qml.from_qasm(qasm_code, measurements=[]) + + >>> print(qml.draw(loaded_circuit)()) + 0: ──H──┤↗├──RZ(0.24)─╭●─┤ + 1: ───────────────────╰X─┤ + + Note that calling the quantum function returns the same empty list we passed. + + >>> loaded_circuit() + [] The measurements can also be passed directly to the function when creating the quantum function, making it possible to create a PennyLane circuit with - :class:`qml.QNode `: + :class:`qml.QNode `. - >>> measurements = [qml.var(qml.Y(0))] - >>> circuit = qml.QNode(qml.from_qasm(hadamard_qasm, measurements), dev) - >>> circuit() - [tensor(1., requires_grad=True)] + .. code-block:: python - Mid-circuit measurements inside the QASM code can also be interpreted. + dev = qml.device("default.qubit") + measurements = [qml.var(qml.Y(0))] + circuit = qml.QNode(qml.from_qasm(qasm_code, measurements), dev) - .. code-block:: python + >>> print(qml.draw(circuit)()) + 0: ──H──┤↗├──RZ(0.24)─╭●─┤ Var[Y] + 1: ───────────────────╰X─┤ - hadamard_qasm = 'OPENQASM 2.0;' \\ - 'include "qelib1.inc";' \\ - 'qreg q[2];' \\ - 'creg c[2];' \\ - 'h q[0];' \\ - 'measure q[0] -> c[0];' \\ - 'rz(0.24) q[0];' \\ - 'cx q[0], q[1];' \\ - 'measure q -> c;' + We can also take advantage of the mid-circuit measurements inside the QASM code. - dev = qml.device("default.qubit") - loaded_circuit = qml.from_qasm(hadamard_qasm, measurements=None) + .. code-block:: python + + loaded_circuit = qml.from_qasm(qasm_code) @qml.qnode(dev) def circuit(): - mid_measure, m0, m1 = loaded_circuit() + mid_measure, *_ = loaded_circuit() qml.cond(mid_measure == 0, qml.RX)(np.pi / 2, 0) - return [qml.expval(qml.measure(0))] + return [qml.expval(qml.Z(0))] - >>> circuit() - [tensor(0.75, requires_grad=True)] + >>> print(qml.draw(circuit)()) + 0: ──H──┤↗├──RZ(0.24)─╭●──┤↗├──RX(1.57)─┤ + 1: ──────║────────────╰X──┤↗├──║────────┤ + ╚═════════════════════╝ You can also load the contents of a QASM file: .. code-block:: python - >>> with open("hadamard_circuit.qasm", "r") as f: - ... my_circuit = qml.from_qasm(f.read()) + # save the qasm code in a file + import locale + from pathlib import Path - The ``my_circuit`` template can now be used within QNodes, as a - two-wire quantum template. + filename = "circuit.qasm" + with Path(filename).open("w", encoding=locale.getpreferredencoding(False)) as f: + f.write(qasm_code) - >>> @qml.qnode(dev) - >>> def circuit(x): - >>> qml.RX(x, wires=1) - >>> my_circuit(wires=(1, 0)) - >>> return qml.expval(qml.Z(0)) + with open("circuit.qasm", "r") as f: + loaded_circuit = qml.from_qasm(f.read()) + + The ``loaded_circuit`` function can now be used within a :class:`qml.QNode ` as a two-wire quantum template. + .. code-block:: python + + @qml.qnode(dev) + def circuit(x): + qml.RX(x, wires=1) + loaded_circuit(wires=(0, 1)) + return qml.expval(qml.Z(0)) + + >>> print(qml.draw(circuit)(1.23)) + 0: ──H─────────┤↗├──RZ(0.24)─╭●──┤↗├─┤ + 1: ──RX(1.23)────────────────╰X──┤↗├─┤ """ + try: plugin_converter = plugin_converters["qasm"].load() except Exception as e: # pragma: no cover @@ -507,16 +532,6 @@ def circuit(): "Failed to load the qasm plugin. Please ensure that the pennylane-qiskit package is installed." ) from e - if measurements is False: - measurements = [] - if "measure" in quantum_circuit: - warnings.warn( - "The current default behaviour of removing measurements in the QASM code " - "is deprecated. Set measurements=None to keep existing measurements in the QASM " - "code or set measurements=[] to remove them from the returned circuit. Starting " - "in version 0.38, measurements=None will be the new default.", - qml.PennyLaneDeprecationWarning, - ) return plugin_converter(quantum_circuit, measurements=measurements) diff --git a/tests/test_io.py b/tests/test_io.py index fa3ed2dc607..2cf1b22472b 100644 --- a/tests/test_io.py +++ b/tests/test_io.py @@ -145,16 +145,6 @@ def test_from_qasm(self, mock_plugin_converters): if mock_plugin_converters[plugin_converter].called and plugin_converter != "qasm": raise RuntimeError(f"The other plugin converter {plugin_converter} was called.") - def test_from_qasm_deprecated(self, mock_plugin_converters): - """Tests that the current default behaviour of from_qasm is deprecated.""" - - with pytest.warns(qml.PennyLaneDeprecationWarning, match="The current default behaviour"): - qml.from_qasm("measure q[i] -> c[i];") - - called_args, called_kwargs = mock_plugin_converters["qasm"].call_args - assert called_args == ("measure q[i] -> c[i];",) - assert called_kwargs == {"measurements": []} - @pytest.mark.parametrize( "method, entry_point_name, args, kwargs", [ From 49a41b7a8079b6e28cf20fc781fb9d99519fded3 Mon Sep 17 00:00:00 2001 From: EmilianoG-byte Date: Wed, 10 Jul 2024 17:01:10 -0400 Subject: [PATCH 02/14] add entries to deprecations and changelog --- doc/development/deprecations.rst | 14 ++++++-------- doc/releases/changelog-dev.md | 5 +++++ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/doc/development/deprecations.rst b/doc/development/deprecations.rst index 97ef6cb6eee..f1705413317 100644 --- a/doc/development/deprecations.rst +++ b/doc/development/deprecations.rst @@ -21,14 +21,6 @@ Pending deprecations - Deprecated in v0.37 - Will be removed in v0.38 -* ``qml.from_qasm`` will no longer remove measurements from the QASM code. Calling ``qml.from_qasm`` - on a circuit containing measurements without specifying ``measurements`` will raise a deprecation - warning in v0.37, and in v0.38, the default behaviour will be changed to keeping measurements. Use - ``measurements=[]`` to remove measurements from the original circuit. - - - Deprecated in v0.37 - - Default behaviour will be changed in v0.38 - New operator arithmetic deprecations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -73,6 +65,12 @@ Other deprecations Completed deprecation cycles ---------------------------- +* ``qml.from_qasm`` no longer removes measurements from the QASM code. Use + ``measurements=[]`` to remove measurements from the original circuit. + + - Deprecated in v0.37 + - Default behaviour changed in v0.38 + * ``qml.from_qasm_file`` has been removed. Instead, the user can open the file and then load its content using ``qml.from_qasm``. >>> with open("test.qasm", "r") as f: diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md index 6e17f1212b2..686834616b3 100644 --- a/doc/releases/changelog-dev.md +++ b/doc/releases/changelog-dev.md @@ -25,6 +25,10 @@

Breaking changes 💔

+* ``qml.from_qasm`` no longer removes measurements from the QASM code. Use + ``measurements=[]`` to remove measurements from the original circuit. + [(#5982)](https://github.com/PennyLaneAI/pennylane/pull/5982) +

Deprecations 👋

Documentation 📝

@@ -35,6 +39,7 @@ This release contains contributions from (in alphabetical order): Yushao Chen, +Emiliano Godinez, Christina Lee, William Maxwell, Vincent Michaud-Rioux, From a3e3a71332a3ca7086046a8f758cdf66227850bf Mon Sep 17 00:00:00 2001 From: EmilianoG-byte Date: Thu, 11 Jul 2024 16:54:29 -0400 Subject: [PATCH 03/14] add additional explanation to from_qasm docstring --- pennylane/io.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pennylane/io.py b/pennylane/io.py index 351e5c73bb4..e88e338ff4d 100644 --- a/pennylane/io.py +++ b/pennylane/io.py @@ -415,12 +415,12 @@ def from_qasm(quantum_circuit: str, measurements=None): Args: quantum_circuit (str): a QASM string containing a valid quantum circuit measurements (None | MeasurementProcess | list[MeasurementProcess]): an optional PennyLane - measurement or list of PennyLane measurements that overrides any terminal measurements + measurement or list of PennyLane measurements that overrides the terminal measurements that may be present in the input circuit. Defaults to ``None``, such that existing measurements - in the input circuit are kept. + in the input circuit are kept. Mid-circuit measurements are kept either way. Returns: - function: the PennyLane quantum function created based on the QASM string. This function itself returns the mid-circuit measurements plus the terminal measurements by default (``measurements=None``), and returns the ``measurements`` otherwise. + function: the PennyLane quantum function created based on the QASM string. This function itself returns the mid-circuit measurements plus the terminal measurements by default (``measurements=None``), and returns **only** the measurements from the ``measurements`` argument otherwise. **Example:** @@ -478,7 +478,7 @@ def from_qasm(quantum_circuit: str, measurements=None): 0: ──H──┤↗├──RZ(0.24)─╭●─┤ Var[Y] 1: ───────────────────╰X─┤ - We can also take advantage of the mid-circuit measurements inside the QASM code. + We can take advantage of the mid-circuit measurements inside the QASM code by calling the returned function. .. code-block:: python @@ -495,7 +495,7 @@ def circuit(): 1: ──────║────────────╰X──┤↗├──║────────┤ ╚═════════════════════╝ - You can also load the contents of a QASM file: + We can also load the contents of a QASM file. .. code-block:: python From b363d3308be0379315b89ed96e0fd04a3db31f5c Mon Sep 17 00:00:00 2001 From: Cristian Emiliano Godinez Ramirez <57567043+EmilianoG-byte@users.noreply.github.com> Date: Fri, 12 Jul 2024 11:20:34 -0400 Subject: [PATCH 04/14] Apply suggestions from code review Co-authored-by: Isaac De Vlugt <34751083+isaacdevlugt@users.noreply.github.com> --- pennylane/io.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pennylane/io.py b/pennylane/io.py index e88e338ff4d..950fac6d4f2 100644 --- a/pennylane/io.py +++ b/pennylane/io.py @@ -416,7 +416,7 @@ def from_qasm(quantum_circuit: str, measurements=None): quantum_circuit (str): a QASM string containing a valid quantum circuit measurements (None | MeasurementProcess | list[MeasurementProcess]): an optional PennyLane measurement or list of PennyLane measurements that overrides the terminal measurements - that may be present in the input circuit. Defaults to ``None``, such that existing measurements + that may be present in the input circuit. Defaults to ``None``, such that all existing measurements in the input circuit are kept. Mid-circuit measurements are kept either way. Returns: @@ -449,7 +449,7 @@ def from_qasm(quantum_circuit: str, measurements=None): MeasurementValue(wires=[0]), MeasurementValue(wires=[1])) - To remove all terminal measurements, set ``measurements=[]`` which removes the existing terminal measurements, while keeping the mid circuit measurements. + To remove all terminal measurements, set ``measurements=[]``, which removes the existing terminal measurements and keeps the mid-circuit measurements. .. code-block:: python @@ -459,7 +459,7 @@ def from_qasm(quantum_circuit: str, measurements=None): 0: ──H──┤↗├──RZ(0.24)─╭●─┤ 1: ───────────────────╰X─┤ - Note that calling the quantum function returns the same empty list we passed. + Note that calling the quantum function returns the same empty list that we originally passed in. >>> loaded_circuit() [] @@ -472,7 +472,7 @@ def from_qasm(quantum_circuit: str, measurements=None): dev = qml.device("default.qubit") measurements = [qml.var(qml.Y(0))] - circuit = qml.QNode(qml.from_qasm(qasm_code, measurements), dev) + circuit = qml.QNode(qml.from_qasm(qasm_code, measurements = measurements), dev) >>> print(qml.draw(circuit)()) 0: ──H──┤↗├──RZ(0.24)─╭●─┤ Var[Y] From 5a22a8090e15a03315b933e872c760888d92be1e Mon Sep 17 00:00:00 2001 From: EmilianoG-byte Date: Fri, 12 Jul 2024 12:12:40 -0400 Subject: [PATCH 05/14] create separate sections for examples in from_qasm --- pennylane/io.py | 118 ++++++++++++++++++++++++++---------------------- 1 file changed, 64 insertions(+), 54 deletions(-) diff --git a/pennylane/io.py b/pennylane/io.py index 950fac6d4f2..c8a6856a5cb 100644 --- a/pennylane/io.py +++ b/pennylane/io.py @@ -417,7 +417,7 @@ def from_qasm(quantum_circuit: str, measurements=None): measurements (None | MeasurementProcess | list[MeasurementProcess]): an optional PennyLane measurement or list of PennyLane measurements that overrides the terminal measurements that may be present in the input circuit. Defaults to ``None``, such that all existing measurements - in the input circuit are kept. Mid-circuit measurements are kept either way. + in the input circuit are returned. See :ref:`removing-measuremenets` for details. Returns: function: the PennyLane quantum function created based on the QASM string. This function itself returns the mid-circuit measurements plus the terminal measurements by default (``measurements=None``), and returns **only** the measurements from the ``measurements`` argument otherwise. @@ -444,85 +444,95 @@ def from_qasm(quantum_circuit: str, measurements=None): Calling the quantum function returns a tuple containing the mid-circuit measurements and the terminal measurements. - >>> my_circuit() + >>> loaded_circuit() (MeasurementValue(wires=[0]), MeasurementValue(wires=[0]), MeasurementValue(wires=[1])) - To remove all terminal measurements, set ``measurements=[]``, which removes the existing terminal measurements and keeps the mid-circuit measurements. + .. details:: + .. _removing-measuremenets: + :title: Removing terminal measurements - .. code-block:: python + To remove all terminal measurements, set ``measurements=[]``. This removes the existing terminal measurements and keeps the mid-circuit measurements. - loaded_circuit = qml.from_qasm(qasm_code, measurements=[]) + .. code-block:: python - >>> print(qml.draw(loaded_circuit)()) - 0: ──H──┤↗├──RZ(0.24)─╭●─┤ - 1: ───────────────────╰X─┤ + loaded_circuit = qml.from_qasm(qasm_code, measurements=[]) - Note that calling the quantum function returns the same empty list that we originally passed in. + >>> print(qml.draw(loaded_circuit)()) + 0: ──H──┤↗├──RZ(0.24)─╭●─┤ + 1: ───────────────────╰X─┤ - >>> loaded_circuit() - [] + Calling the quantum function returns the same empty list that we originally passed in. - The measurements can also be passed directly to the function when creating the - quantum function, making it possible to create a PennyLane circuit with - :class:`qml.QNode `. + >>> loaded_circuit() + [] - .. code-block:: python + Note that mid-circuit measurements are always applied, but are only returned when ``measurements=None``. - dev = qml.device("default.qubit") - measurements = [qml.var(qml.Y(0))] - circuit = qml.QNode(qml.from_qasm(qasm_code, measurements = measurements), dev) + :title: Creating a Quantum Node - >>> print(qml.draw(circuit)()) - 0: ──H──┤↗├──RZ(0.24)─╭●─┤ Var[Y] - 1: ───────────────────╰X─┤ + A list of measurements can also be passed directly to ``from_qasm`` using the ``measurements`` argument, making it possible to create a PennyLane circuit with + :class:`qml.QNode `. - We can take advantage of the mid-circuit measurements inside the QASM code by calling the returned function. + .. code-block:: python - .. code-block:: python + dev = qml.device("default.qubit") + measurements = [qml.var(qml.Y(0))] + circuit = qml.QNode(qml.from_qasm(qasm_code, measurements = measurements), dev) - loaded_circuit = qml.from_qasm(qasm_code) + >>> print(qml.draw(circuit)()) + 0: ──H──┤↗├──RZ(0.24)─╭●─┤ Var[Y] + 1: ───────────────────╰X─┤ + :title: Using conditional operations - @qml.qnode(dev) - def circuit(): - mid_measure, *_ = loaded_circuit() - qml.cond(mid_measure == 0, qml.RX)(np.pi / 2, 0) - return [qml.expval(qml.Z(0))] + We can take advantage of the mid-circuit measurements inside the QASM code by calling the returned function within a :class:`qml.QNode `. - >>> print(qml.draw(circuit)()) - 0: ──H──┤↗├──RZ(0.24)─╭●──┤↗├──RX(1.57)─┤ - 1: ──────║────────────╰X──┤↗├──║────────┤ - ╚═════════════════════╝ + .. code-block:: python - We can also load the contents of a QASM file. + loaded_circuit = qml.from_qasm(qasm_code) - .. code-block:: python + @qml.qnode(dev) + def circuit(): + mid_measure, *_ = loaded_circuit() + qml.cond(mid_measure == 0, qml.RX)(np.pi / 2, 0) + return [qml.expval(qml.Z(0))] - # save the qasm code in a file - import locale - from pathlib import Path + >>> print(qml.draw(circuit)()) + 0: ──H──┤↗├──RZ(0.24)─╭●──┤↗├──RX(1.57)─┤ + 1: ──────║────────────╰X──┤↗├──║────────┤ + ╚═════════════════════╝ - filename = "circuit.qasm" - with Path(filename).open("w", encoding=locale.getpreferredencoding(False)) as f: - f.write(qasm_code) + :title: Importing from a QASM file - with open("circuit.qasm", "r") as f: - loaded_circuit = qml.from_qasm(f.read()) + We can also load the contents of a QASM file. - The ``loaded_circuit`` function can now be used within a :class:`qml.QNode ` as a two-wire quantum template. + .. code-block:: python - .. code-block:: python + # save the qasm code in a file + import locale + from pathlib import Path - @qml.qnode(dev) - def circuit(x): - qml.RX(x, wires=1) - loaded_circuit(wires=(0, 1)) - return qml.expval(qml.Z(0)) - - >>> print(qml.draw(circuit)(1.23)) - 0: ──H─────────┤↗├──RZ(0.24)─╭●──┤↗├─┤ - 1: ──RX(1.23)────────────────╰X──┤↗├─┤ + filename = "circuit.qasm" + with Path(filename).open("w", encoding=locale.getpreferredencoding(False)) as f: + f.write(qasm_code) + + with open("circuit.qasm", "r") as f: + loaded_circuit = qml.from_qasm(f.read()) + + The ``loaded_circuit`` function can now be used within a :class:`qml.QNode ` as a two-wire quantum template. + + .. code-block:: python + + @qml.qnode(dev) + def circuit(x): + qml.RX(x, wires=1) + loaded_circuit(wires=(0, 1)) + return qml.expval(qml.Z(0)) + + >>> print(qml.draw(circuit)(1.23)) + 0: ──H─────────┤↗├──RZ(0.24)─╭●──┤↗├─┤ + 1: ──RX(1.23)────────────────╰X──┤↗├─┤ """ try: From a0bb593d5ed8fc5e87f31faf526a3fd1e65a9130 Mon Sep 17 00:00:00 2001 From: EmilianoG-byte Date: Fri, 12 Jul 2024 14:24:39 -0400 Subject: [PATCH 06/14] fix sections separation --- pennylane/io.py | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/pennylane/io.py b/pennylane/io.py index c8a6856a5cb..923de4b273a 100644 --- a/pennylane/io.py +++ b/pennylane/io.py @@ -449,8 +449,22 @@ def from_qasm(quantum_circuit: str, measurements=None): MeasurementValue(wires=[0]), MeasurementValue(wires=[1])) + A list of measurements can also be passed directly to ``from_qasm`` using the ``measurements`` argument, making it possible to create a PennyLane circuit with + :class:`qml.QNode `. + + .. code-block:: python + + dev = qml.device("default.qubit") + measurements = [qml.var(qml.Y(0))] + circuit = qml.QNode(qml.from_qasm(qasm_code, measurements = measurements), dev) + + >>> print(qml.draw(circuit)()) + 0: ──H──┤↗├──RZ(0.24)─╭●─┤ Var[Y] + 1: ───────────────────╰X─┤ + + .. _removing-measuremenets: + .. details:: - .. _removing-measuremenets: :title: Removing terminal measurements To remove all terminal measurements, set ``measurements=[]``. This removes the existing terminal measurements and keeps the mid-circuit measurements. @@ -470,20 +484,7 @@ def from_qasm(quantum_circuit: str, measurements=None): Note that mid-circuit measurements are always applied, but are only returned when ``measurements=None``. - :title: Creating a Quantum Node - - A list of measurements can also be passed directly to ``from_qasm`` using the ``measurements`` argument, making it possible to create a PennyLane circuit with - :class:`qml.QNode `. - - .. code-block:: python - - dev = qml.device("default.qubit") - measurements = [qml.var(qml.Y(0))] - circuit = qml.QNode(qml.from_qasm(qasm_code, measurements = measurements), dev) - - >>> print(qml.draw(circuit)()) - 0: ──H──┤↗├──RZ(0.24)─╭●─┤ Var[Y] - 1: ───────────────────╰X─┤ + .. details:: :title: Using conditional operations We can take advantage of the mid-circuit measurements inside the QASM code by calling the returned function within a :class:`qml.QNode `. @@ -503,6 +504,7 @@ def circuit(): 1: ──────║────────────╰X──┤↗├──║────────┤ ╚═════════════════════╝ + .. details:: :title: Importing from a QASM file We can also load the contents of a QASM file. From 655cc8cee779f55cf7009b46e4ee12232b41cd3a Mon Sep 17 00:00:00 2001 From: EmilianoG-byte Date: Fri, 12 Jul 2024 16:19:17 -0400 Subject: [PATCH 07/14] fix sphinx reference problem --- pennylane/io.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/pennylane/io.py b/pennylane/io.py index 923de4b273a..b774d07713d 100644 --- a/pennylane/io.py +++ b/pennylane/io.py @@ -408,7 +408,7 @@ def from_qiskit_op(qiskit_op, params=None, wires=None): def from_qasm(quantum_circuit: str, measurements=None): - """ + r""" Loads quantum circuits from a QASM string using the converter in the PennyLane-Qiskit plugin. @@ -417,7 +417,7 @@ def from_qasm(quantum_circuit: str, measurements=None): measurements (None | MeasurementProcess | list[MeasurementProcess]): an optional PennyLane measurement or list of PennyLane measurements that overrides the terminal measurements that may be present in the input circuit. Defaults to ``None``, such that all existing measurements - in the input circuit are returned. See :ref:`removing-measuremenets` for details. + in the input circuit are returned. See **Removing terminal measurements** for details. Returns: function: the PennyLane quantum function created based on the QASM string. This function itself returns the mid-circuit measurements plus the terminal measurements by default (``measurements=None``), and returns **only** the measurements from the ``measurements`` argument otherwise. @@ -449,8 +449,7 @@ def from_qasm(quantum_circuit: str, measurements=None): MeasurementValue(wires=[0]), MeasurementValue(wires=[1])) - A list of measurements can also be passed directly to ``from_qasm`` using the ``measurements`` argument, making it possible to create a PennyLane circuit with - :class:`qml.QNode `. + A list of measurements can also be passed directly to ``from_qasm`` using the ``measurements`` argument, making it possible to create a PennyLane circuit with :class:`qml.QNode `. .. code-block:: python @@ -462,8 +461,6 @@ def from_qasm(quantum_circuit: str, measurements=None): 0: ──H──┤↗├──RZ(0.24)─╭●─┤ Var[Y] 1: ───────────────────╰X─┤ - .. _removing-measuremenets: - .. details:: :title: Removing terminal measurements From cf04f89961d737527cb5f98a6c67f3eb29933c12 Mon Sep 17 00:00:00 2001 From: EmilianoG-byte Date: Fri, 12 Jul 2024 16:19:34 -0400 Subject: [PATCH 08/14] fix drawing --- pennylane/io.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane/io.py b/pennylane/io.py index b774d07713d..a225346b4f5 100644 --- a/pennylane/io.py +++ b/pennylane/io.py @@ -499,7 +499,7 @@ def circuit(): >>> print(qml.draw(circuit)()) 0: ──H──┤↗├──RZ(0.24)─╭●──┤↗├──RX(1.57)─┤ 1: ──────║────────────╰X──┤↗├──║────────┤ - ╚═════════════════════╝ + ╚═════════════════════╝ .. details:: :title: Importing from a QASM file From cecd59bf7b0409d2db20749e70a44031f38263be Mon Sep 17 00:00:00 2001 From: EmilianoG-byte Date: Mon, 15 Jul 2024 12:07:05 -0400 Subject: [PATCH 09/14] fix identation, add example, and fix qasm code --- pennylane/io.py | 50 +++++++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/pennylane/io.py b/pennylane/io.py index a225346b4f5..a111a3825fe 100644 --- a/pennylane/io.py +++ b/pennylane/io.py @@ -417,7 +417,7 @@ def from_qasm(quantum_circuit: str, measurements=None): measurements (None | MeasurementProcess | list[MeasurementProcess]): an optional PennyLane measurement or list of PennyLane measurements that overrides the terminal measurements that may be present in the input circuit. Defaults to ``None``, such that all existing measurements - in the input circuit are returned. See **Removing terminal measurements** for details. + in the input circuit are returned. See *Removing terminal measurements* for details. Returns: function: the PennyLane quantum function created based on the QASM string. This function itself returns the mid-circuit measurements plus the terminal measurements by default (``measurements=None``), and returns **only** the measurements from the ``measurements`` argument otherwise. @@ -426,15 +426,15 @@ def from_qasm(quantum_circuit: str, measurements=None): .. code-block:: python - qasm_code = 'OPENQASM 2.0;'\\ - 'include "qelib1.inc";'\\ - 'qreg q[2];'\\ - 'creg c[2];'\\ - 'h q[0];'\\ - 'measure q[0] -> c[0];'\\ - 'rz(0.24) q[0];'\\ - 'cx q[0], q[1];'\\ - 'measure q -> c;' + qasm_code = \"\"\"OPENQASM 2.0; + include "qelib1.inc"; + qreg q[2]; + creg c[2]; + h q[0]; + measure q[0] -> c[0]; + rz(0.24) q[0]; + cx q[0], q[1]; + measure q -> c;\"\"\" loaded_circuit = qml.from_qasm(qasm_code) @@ -451,15 +451,15 @@ def from_qasm(quantum_circuit: str, measurements=None): A list of measurements can also be passed directly to ``from_qasm`` using the ``measurements`` argument, making it possible to create a PennyLane circuit with :class:`qml.QNode `. - .. code-block:: python + .. code-block:: python - dev = qml.device("default.qubit") - measurements = [qml.var(qml.Y(0))] - circuit = qml.QNode(qml.from_qasm(qasm_code, measurements = measurements), dev) + dev = qml.device("default.qubit") + measurements = [qml.var(qml.Y(0))] + circuit = qml.QNode(qml.from_qasm(qasm_code, measurements = measurements), dev) - >>> print(qml.draw(circuit)()) - 0: ──H──┤↗├──RZ(0.24)─╭●─┤ Var[Y] - 1: ───────────────────╰X─┤ + >>> print(qml.draw(circuit)()) + 0: ──H──┤↗├──RZ(0.24)─╭●─┤ Var[Y] + 1: ───────────────────╰X─┤ .. details:: :title: Removing terminal measurements @@ -479,7 +479,21 @@ def from_qasm(quantum_circuit: str, measurements=None): >>> loaded_circuit() [] - Note that mid-circuit measurements are always applied, but are only returned when ``measurements=None``. + Note that mid-circuit measurements are always applied, but are only returned when ``measurements=None``. This can be exemplified by using the ``loaded_circuit`` without the terminal measurements within a ``QNode``. + + .. code-block:: python + + dev = qml.device("default.qubit") + + @qml.qnode(dev) + def circuit(): + loaded_circuit() + return qml.expval(qml.Z(1)) + + >>> print(qml.draw(circuit)()) + 0: ──H──┤↗├──RZ(0.24)─╭●─┤ + 1: ───────────────────╰X─┤ + .. details:: :title: Using conditional operations From 5f41895db6ea92098bb7042d3fe70305f4692629 Mon Sep 17 00:00:00 2001 From: EmilianoG-byte Date: Mon, 15 Jul 2024 13:43:15 -0400 Subject: [PATCH 10/14] add intentation to example --- pennylane/io.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pennylane/io.py b/pennylane/io.py index a111a3825fe..96f14a885ab 100644 --- a/pennylane/io.py +++ b/pennylane/io.py @@ -427,14 +427,14 @@ def from_qasm(quantum_circuit: str, measurements=None): .. code-block:: python qasm_code = \"\"\"OPENQASM 2.0; - include "qelib1.inc"; - qreg q[2]; - creg c[2]; - h q[0]; - measure q[0] -> c[0]; - rz(0.24) q[0]; - cx q[0], q[1]; - measure q -> c;\"\"\" + include "qelib1.inc"; + qreg q[2]; + creg c[2]; + h q[0]; + measure q[0] -> c[0]; + rz(0.24) q[0]; + cx q[0], q[1]; + measure q -> c;\"\"\" loaded_circuit = qml.from_qasm(qasm_code) From d6963f6178d395fd7c56eac6baf1fa1e63a769dc Mon Sep 17 00:00:00 2001 From: EmilianoG-byte Date: Mon, 15 Jul 2024 14:57:27 -0400 Subject: [PATCH 11/14] add back backslashes on qasm example code --- pennylane/io.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/pennylane/io.py b/pennylane/io.py index 96f14a885ab..a75ad48f38d 100644 --- a/pennylane/io.py +++ b/pennylane/io.py @@ -426,15 +426,15 @@ def from_qasm(quantum_circuit: str, measurements=None): .. code-block:: python - qasm_code = \"\"\"OPENQASM 2.0; - include "qelib1.inc"; - qreg q[2]; - creg c[2]; - h q[0]; - measure q[0] -> c[0]; - rz(0.24) q[0]; - cx q[0], q[1]; - measure q -> c;\"\"\" + qasm_code = 'OPENQASM 2.0;' \\ + 'include "qelib1.inc";' \\ + 'qreg q[2];' \\ + 'creg c[2];' \\ + 'h q[0];' \\ + 'measure q[0] -> c[0];' \\ + 'rz(0.24) q[0];' \\ + 'cx q[0], q[1];' \\ + 'measure q -> c;' loaded_circuit = qml.from_qasm(qasm_code) From 3922eb00df0ce3d20fa2113dabb124aecc862989 Mon Sep 17 00:00:00 2001 From: EmilianoG-byte Date: Mon, 15 Jul 2024 17:43:41 -0400 Subject: [PATCH 12/14] erase import temporarily to make sphinx work --- pennylane/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pennylane/__init__.py b/pennylane/__init__.py index c0388db8536..99cfada8f6e 100644 --- a/pennylane/__init__.py +++ b/pennylane/__init__.py @@ -63,7 +63,8 @@ from pennylane.configuration import Configuration from pennylane.drawer import draw, draw_mpl from pennylane.tracker import Tracker -from pennylane.io import * + +# from pennylane.io import * from pennylane.measurements import ( counts, density_matrix, From 0b498a4a7af472c65e3ef1d811b8bb4e32bc0770 Mon Sep 17 00:00:00 2001 From: EmilianoG-byte Date: Mon, 15 Jul 2024 23:20:06 -0400 Subject: [PATCH 13/14] bring back io module --- pennylane/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane/__init__.py b/pennylane/__init__.py index 99cfada8f6e..04b7e4f24f9 100644 --- a/pennylane/__init__.py +++ b/pennylane/__init__.py @@ -64,7 +64,7 @@ from pennylane.drawer import draw, draw_mpl from pennylane.tracker import Tracker -# from pennylane.io import * +from pennylane.io import * from pennylane.measurements import ( counts, density_matrix, From 07dd4142058727a61ee707bff0eb43e06d6a02d9 Mon Sep 17 00:00:00 2001 From: Cristian Emiliano Godinez Ramirez <57567043+EmilianoG-byte@users.noreply.github.com> Date: Tue, 16 Jul 2024 10:42:46 -0400 Subject: [PATCH 14/14] Update pennylane/io.py Co-authored-by: lillian542 <38584660+lillian542@users.noreply.github.com> --- pennylane/io.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pennylane/io.py b/pennylane/io.py index a75ad48f38d..e3a3cf14ebe 100644 --- a/pennylane/io.py +++ b/pennylane/io.py @@ -426,14 +426,14 @@ def from_qasm(quantum_circuit: str, measurements=None): .. code-block:: python - qasm_code = 'OPENQASM 2.0;' \\ - 'include "qelib1.inc";' \\ - 'qreg q[2];' \\ - 'creg c[2];' \\ - 'h q[0];' \\ - 'measure q[0] -> c[0];' \\ - 'rz(0.24) q[0];' \\ - 'cx q[0], q[1];' \\ + qasm_code = 'OPENQASM 2.0;' \ + 'include "qelib1.inc";' \ + 'qreg q[2];' \ + 'creg c[2];' \ + 'h q[0];' \ + 'measure q[0] -> c[0];' \ + 'rz(0.24) q[0];' \ + 'cx q[0], q[1];' \ 'measure q -> c;' loaded_circuit = qml.from_qasm(qasm_code)