diff --git a/.github/stable/external.txt b/.github/stable/external.txt index 7749c3a7572..23201352049 100644 --- a/.github/stable/external.txt +++ b/.github/stable/external.txt @@ -117,8 +117,8 @@ packaging==24.1 pandocfilters==1.5.1 parso==0.8.4 pathspec==0.12.1 -PennyLane-Catalyst==0.6.0 -PennyLane_Lightning==0.36.0 +PennyLane-Catalyst==0.7.0 +PennyLane_Lightning==0.37.0 pexpect==4.9.0 pillow==10.3.0 platformdirs==4.2.2 diff --git a/.github/workflows/install_deps/action.yml b/.github/workflows/install_deps/action.yml index 0e6fc6d2796..1ff648a5c8d 100644 --- a/.github/workflows/install_deps/action.yml +++ b/.github/workflows/install_deps/action.yml @@ -95,6 +95,11 @@ runs: python setup.py bdist_wheel pip install dist/PennyLane*.whl + - name: Install Catalyst + shell: bash + if: inputs.install_catalyst_after_pennylane == 'true' + run: pip install --upgrade pennylane-catalyst + - name: Install PennyLane-Lightning master shell: bash if: inputs.install_pennylane_lightning_master == 'true' diff --git a/.github/workflows/interface-unit-tests.yml b/.github/workflows/interface-unit-tests.yml index ba2fc38154f..07dff8933f6 100644 --- a/.github/workflows/interface-unit-tests.yml +++ b/.github/workflows/interface-unit-tests.yml @@ -362,6 +362,10 @@ jobs: install_jax: true install_tensorflow: true install_pytorch: false + # This is required during the release process when the latest released version of + # catalyst requires the latest version of pennylane that is about to be released. + # Installing catalyst after pennylane to make sure that the latest catalyst is used. + install_catalyst_after_pennylane: true # using lightning master does not work for the tests with external libraries install_pennylane_lightning_master: false pytest_coverage_flags: ${{ inputs.pytest_coverage_flags }} diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 6a3e2a89416..a27968c3d21 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -59,6 +59,11 @@ on: required: false type: string default: '' + install_catalyst_after_pennylane: + description: Indicate if the latest Catalyst should be installed after PennyLane + required: false + type: boolean + default: false install_pennylane_lightning_master: description: Indicate if PennyLane-Lightning should be installed from the master branch required: false @@ -147,6 +152,7 @@ jobs: install_tensorflow: ${{ inputs.install_tensorflow }} install_jax: ${{ inputs.install_jax }} additional_pip_packages: ${{ inputs.additional_pip_packages }} + install_catalyst_after_pennylane: ${{ inputs.install_catalyst_after_pennylane }} install_pennylane_lightning_master: ${{ inputs.install_pennylane_lightning_master }} requirements_file: ${{ inputs.requirements_file }} diff --git a/doc/releases/changelog-0.37.0.md b/doc/releases/changelog-0.37.0.md index 046df5dcc63..969b5673c85 100644 --- a/doc/releases/changelog-0.37.0.md +++ b/doc/releases/changelog-0.37.0.md @@ -4,8 +4,6 @@

New features since last release

-

Execute faster with Default Tensor 🔗

-

Execute wide circuits with Default Tensor 🔗

* A new `default.tensor` device is now available for performing @@ -19,27 +17,41 @@ [(#5795)](https://github.com/PennyLaneAI/pennylane/pull/5795) Either method can be selected when instantiating the `default.tensor` device by setting the - `method` keyword argument to `"tn"` (tensor network) or `"mps"` (matrix product state). This - device can simulate a large number of qubits. Take this example that - simulates 1000 qubits with a shallow circuit in a few seconds! + `method` keyword argument to `"tn"` (tensor network) or `"mps"` (matrix product state). + + There are + [several templates in PennyLane](https://docs.pennylane.ai/en/stable/introduction/templates.html#tensor-networks) + that are tensor-network focused, which are excellent candidates for the `"tn"` method for + `default.tensor`. The following example shows how a circuit comprising gates in a tree tensor + network architecture can be efficiently simulated using `method="tn"`. ```python import pennylane as qml - num_qubits = 1000 - dev = qml.device("default.tensor", method="mps") + n_wires = 16 + dev = qml.device("default.tensor", method="tn") + + def block(weights, wires): + qml.CNOT(wires=[wires[0], wires[1]]) + qml.RY(weights[0], wires=wires[0]) + qml.RY(weights[1], wires=wires[1]) + + n_block_wires = 2 + n_params_block = 2 + n_blocks = qml.TTN.get_n_blocks(range(n_wires), n_block_wires) + template_weights = [[0.1, -0.3]] * n_blocks @qml.qnode(dev) - def circuit(): - qml.Hadamard(0) - for i in range(num_qubits - 1): - qml.CNOT([i, i + 1]) - return qml.expval(qml.Z(num_qubits - 1)) + def circuit(template_weights): + for i in range(n_wires): + qml.Hadamard(i) + qml.TTN(range(n_wires), n_block_wires, block, n_params_block, template_weights) + return qml.expval(qml.Z(n_wires - 1)) ``` ```pycon - >>> circuit() - tensor(0., requires_grad=True) + >>> circuit(template_weights) + 0.3839174759751649 ``` For matrix product state simulations (`method="mps"`), we can make the execution be approximate by setting `max_bond_dim` (see the @@ -215,18 +227,18 @@ via the `NoiseModel` class and an `add_noise` transform. For example, `qml.debug_tape()` returns the tape of the circuit, giving access to its operations and drawing: ```pycon - (pldb): tape = qml.debug_tape() - (pldb): print(tape.draw(wire_order=[0,1,2])) + [pldb] tape = qml.debug_tape() + [pldb] print(tape.draw(wire_order=[0,1,2])) 0: ──H─╭●─┤ 2: ────╰X─┤ - (pldb): tape.operations + [pldb] tape.operations [Hadamard(wires=[0]), CNOT(wires=[0, 2])] ``` While `qml.debug_state()` is equivalent to `qml.state()` and gives the current state: ```pycon - (pldb): print(qml.debug_state()) + [pldb] print(qml.debug_state()) [0.70710678+0.j 0. +0.j 0. +0.j 0. +0.j 1. +0.j 0.70710678+0.j 0. +0.j 0. +0.j] ``` @@ -238,9 +250,9 @@ via the `NoiseModel` class and an `add_noise` transform. Finally, to modify a circuit mid-run, simply call the desired PennyLane operations: ```pycon - (pldb) qml.CNOT(wires=(0,2)) + [pldb] qml.CNOT(wires=(0,2)) CNOT(wires=[0, 2]) - (pldb): print(qml.debug_tape().draw(wire_order=[0,1,2])) + [pldb] print(qml.debug_tape().draw(wire_order=[0,1,2])) 0: ──H─╭●─╭●─┤ 2: ────╰X─╰X─┤ ``` @@ -340,10 +352,10 @@ Stay tuned for an in-depth demonstration on using this feature with real-world e ``` ```pycon - >>> print(pl_op) - a⁺(0) a(2) - >>> print(of_op_new) - 1.0 [0^ 2] + >>> print(qml.draw(f, level="device")()) + 0: ──RX(0.28)─╭●────╭X──RX(0.70)─╭●────╭X─┤ + 1: ──RX(0.52)─╰X─╭●─│───RX(0.65)─╰X─╭●─│──┤ + 2: ──RX(0.00)────╰X─╰●──RX(0.03)────╰X─╰●─┤ ```

Improvements 🛠

@@ -637,7 +649,8 @@ Stay tuned for an in-depth demonstration on using this feature with real-world e `base` properties. [(##5772)](https://github.com/PennyLaneAI/pennylane/pull/5772) -

Quantum chemistry

+* New dispatches for `qml.ops.Conditional` and `qml.MeasurementValue` have been added to `qml.equal`. + [(##5772)](https://github.com/PennyLaneAI/pennylane/pull/5772) * The `qml.snapshots` transform now supports arbitrary devices by running a separate tape for each snapshot for unsupported devices. diff --git a/pennylane/compiler/compiler.py b/pennylane/compiler/compiler.py index 74b0e45b5d7..2a4a7575b3b 100644 --- a/pennylane/compiler/compiler.py +++ b/pennylane/compiler/compiler.py @@ -23,7 +23,7 @@ from packaging.version import Version -PL_CATALYST_MIN_VERSION = Version("0.6.0") +PL_CATALYST_MIN_VERSION = Version("0.7.0") class CompileError(Exception): diff --git a/pennylane/debugging/debugger.py b/pennylane/debugging/debugger.py index a3ce35dd682..190f3f696b2 100644 --- a/pennylane/debugging/debugger.py +++ b/pennylane/debugging/debugger.py @@ -141,8 +141,6 @@ def breakpoint(): .. seealso:: :doc:`/code/qml_debugging` - .. seealso:: :doc:`/code/qml_debugging` - **Example** Consider the following python script containing the quantum circuit with breakpoints. diff --git a/setup.py b/setup.py index 6466a02abce..f7b84550a1b 100644 --- a/setup.py +++ b/setup.py @@ -31,7 +31,7 @@ "semantic-version>=2.7", "autoray>=0.6.11", "cachetools", - "pennylane-lightning>=0.36", + "pennylane-lightning>=0.37", "requests", "typing_extensions", "packaging", diff --git a/tests/test_compiler.py b/tests/test_compiler.py index 0529304751a..4b66bf2d061 100644 --- a/tests/test_compiler.py +++ b/tests/test_compiler.py @@ -249,7 +249,6 @@ def circuit(x: float): result_header = "func.func private @circuit(%arg0: tensor) -> tensor" assert result_header in mlir_str - @pytest.mark.xfail(reason="supported once catalyst #768 is merged") def test_qjit_adjoint(self): """Test JIT compilation with adjoint support""" dev = qml.device("lightning.qubit", wires=2) @@ -273,7 +272,6 @@ def func(): assert jnp.allclose(workflow_cl(0.1, [1]), workflow_pl(0.1, [1])) - @pytest.mark.xfail(reason="supported once catalyst #768 is merged") def test_qjit_adjoint_lazy(self): """Test that the lazy kwarg is supported.""" dev = qml.device("lightning.qubit", wires=2) @@ -732,7 +730,6 @@ def f(x): class TestCatalystSample: """Test qml.sample with Catalyst.""" - @pytest.mark.xfail(reason="requires simultaneous catalyst pr") def test_sample_measure(self): """Test that qml.sample can be used with catalyst.measure."""