Skip to content
Open
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
2 changes: 1 addition & 1 deletion .github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
with:
runs-on: ${{ matrix.runs-on }}
setup-mlir: true
llvm-version: "113f01aa82d055410f22a9d03b3468fa68600589"
llvm-version: "8f264586d7521b0e305ca7bb78825aa3382ffef7"

# Downloads the previously generated artifacts and deploys to PyPI on published releases.
deploy:
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
with:
runs-on: ${{ matrix.runs-on }}
setup-mlir: true
llvm-version: "113f01aa82d055410f22a9d03b3468fa68600589"
llvm-version: "8f264586d7521b0e305ca7bb78825aa3382ffef7"

python-coverage:
name: 🐍 Coverage
Expand All @@ -51,7 +51,7 @@ jobs:
enable-ty: true
enable-mypy: false
setup-mlir: true
llvm-version: "113f01aa82d055410f22a9d03b3468fa68600589"
llvm-version: "8f264586d7521b0e305ca7bb78825aa3382ffef7"

build-sdist:
name: πŸš€ CD (sdist)
Expand All @@ -71,7 +71,7 @@ jobs:
with:
runs-on: ${{ matrix.runs-on }}
setup-mlir: true
llvm-version: "113f01aa82d055410f22a9d03b3468fa68600589"
llvm-version: "8f264586d7521b0e305ca7bb78825aa3382ffef7"

cpp-linter:
name: πŸ‡¨β€Œ Lint
Expand All @@ -83,10 +83,10 @@ jobs:
build-project: true
files-changed-only: true
setup-python: true
install-pkgs: "pennylane-catalyst==0.14.1,pennylane==0.44.1"
install-pkgs: "pennylane-catalyst==0.15.0"
cpp-linter-extra-args: "-std=c++20"
setup-mlir: true
llvm-version: "113f01aa82d055410f22a9d03b3468fa68600589"
llvm-version: "8f264586d7521b0e305ca7bb78825aa3382ffef7"
permissions:
contents: read
pull-requests: write
Expand Down
2 changes: 1 addition & 1 deletion .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ build:
- asdf plugin add uv
- asdf install uv latest
- asdf global uv latest
- curl -LsSf https://github.com/munich-quantum-software/setup-mlir/releases/latest/download/setup-mlir.sh | bash -s -- -v 113f01aa82d055410f22a9d03b3468fa68600589 -p $HOME/mlir
- curl -LsSf https://github.com/munich-quantum-software/setup-mlir/releases/latest/download/setup-mlir.sh | bash -s -- -v 8f264586d7521b0e305ca7bb78825aa3382ffef7 -p $HOME/mlir
build:
html:
- MLIR_DIR=$HOME/mlir/lib/cmake/mlir uv run --frozen --no-dev --group docs -m sphinx -T -b html -d docs/_build/doctrees -D language=en docs $READTHEDOCS_OUTPUT/html
Expand Down
22 changes: 15 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,10 @@ Because `pennylane-catalyst` pins to a specific LLVM/MLIR revision, you must bui

### 1) Build the exact LLVM/MLIR revision (locally)

If you want to use a _fast_ pre-built MLIR installation locally (recommended), we provide installation scripts. The scripts require a specific LLVM hash (i.e., 113f01aa82d055410f22a9d03b3468fa68600589) and the desired installation directory to be passed. The scripts automatically download and use a platform-specific zstd binary for decompression, so only tar needs to be installed on the host system.
If you want to use a _fast_ pre-built MLIR installation locally (recommended), we provide installation scripts. The scripts require a specific LLVM hash (i.e., 8f264586d7521b0e305ca7bb78825aa3382ffef7) and the desired installation directory to be passed. The scripts automatically download and use a platform-specific zstd binary for decompression, so only tar needs to be installed on the host system.

```bash
curl -LsSf https://github.com/munich-quantum-software/setup-mlir/releases/latest/download/setup-mlir.sh | bash -s -- -v 113f01aa82d055410f22a9d03b3468fa68600589 -p /path/to/installation
curl -LsSf https://github.com/munich-quantum-software/setup-mlir/releases/latest/download/setup-mlir.sh | bash -s -- -v 8f264586d7521b0e305ca7bb78825aa3382ffef7 -p /path/to/installation

# Export this for your shell/session
export MLIR_DIR="/path/to/installation/lib/cmake/mlir"
Expand All @@ -91,7 +91,7 @@ mkdir -p ~/dev && cd ~/dev
# Clone the exact LLVM revision Catalyst expects
git clone https://github.com/llvm/llvm-project.git
cd llvm-project
git checkout 113f01aa82d055410f22a9d03b3468fa68600589
git checkout 8f264586d7521b0e305ca7bb78825aa3382ffef7

# Configure & build MLIR (Release is recommended)
cmake -S llvm -B build_llvm -G Ninja \
Expand Down Expand Up @@ -154,10 +154,11 @@ from typing import Any

import pennylane as qml
from catalyst.passes import apply_pass
from mqt.core.plugins.catalyst import get_device
from mqt.core.plugins.catalyst import get_catalyst_plugin_abs_path, get_device

# Use get_device() to configure the device for MQT plugin compatibility
device = get_device("lightning.qubit", wires=2)
plugin_path = str(get_catalyst_plugin_abs_path())


# Define your quantum circuit
Expand All @@ -178,7 +179,14 @@ custom_pipeline = [


# JIT compilation with intermediate MLIR files saved
@qml.qjit(target="mlir", autograph=True, keep_intermediate=2, pipelines=custom_pipeline)
@qml.qjit(
target="mlir",
autograph=True,
keep_intermediate=2,
pipelines=custom_pipeline,
pass_plugins={plugin_path},
dialect_plugins={plugin_path},
)
def module() -> Any:
return circuit()

Expand Down Expand Up @@ -245,8 +253,8 @@ The MQT Core Catalyst Plugin is compatible with Python version 3.11 and newer.

The MQT Core Catalyst Plugin relies on some external dependencies:

- [llvm/llvm-project](https://github.com/llvm/llvm-project): A toolkit for the construction of highly optimized compilers, optimizers, and run-time environments (specific revision: `113f01aa82d055410f22a9d03b3468fa68600589`).
- [PennyLaneAI/catalyst](https://github.com/PennyLaneAI/catalyst): A package that enables just-in-time (JIT) compilation of hybrid quantum-classical programs implemented with PennyLane (version == 0.14.1).
- [llvm/llvm-project](https://github.com/llvm/llvm-project): A toolkit for the construction of highly optimized compilers, optimizers, and run-time environments (specific revision: `8f264586d7521b0e305ca7bb78825aa3382ffef7`).
- [PennyLaneAI/catalyst](https://github.com/PennyLaneAI/catalyst): A package that enables just-in-time (JIT) compilation of hybrid quantum-classical programs implemented with PennyLane.
- [MQT Core](https://github.com/munich-quantum-toolkit/core): Provides the MQTOpt MLIR dialect and supporting infrastructure.

Note, both LLVM/MLIR and Catalyst are currently restricted to specific versions. You must build LLVM/MLIR locally from the exact revision specified above and configure CMake to use it (see installation instructions).
Expand Down
2 changes: 1 addition & 1 deletion cmake/ExternalDependencies.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ if(mqt-core_SOURCE_DIR)
set_property(DIRECTORY ${mqt-core_SOURCE_DIR} PROPERTY EXCLUDE_FROM_ALL YES)
endif()

set(CATALYST_VERSION 0.14.1)
set(CATALYST_VERSION 0.15.0)
find_package(Catalyst ${CATALYST_VERSION} QUIET)
if(Catalyst_FOUND)
message(STATUS "Found Catalyst ${Catalyst_VERSION} via CMake find_package.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include <Quantum/IR/QuantumDialect.h>
#include <Quantum/IR/QuantumOps.h>
#include <Quantum/IR/QuantumTypes.h>
#include <cassert>
#include <cstddef>
#include <cstdint>
Expand Down Expand Up @@ -426,7 +427,7 @@ struct ConvertQuantumGlobalPhase final
matchAndRewrite(catalyst::quantum::GlobalPhaseOp op, OpAdaptor adaptor,
ConversionPatternRewriter& rewriter) const override {
// Extract operand(s) and attribute(s)
const auto param = adaptor.getParams();
const auto param = adaptor.getAngle();
const auto inCtrlQubits = adaptor.getInCtrlQubits();
const auto inCtrlValues = adaptor.getInCtrlValues();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include <Quantum/IR/QuantumDialect.h>
#include <Quantum/IR/QuantumOps.h>
#include <Quantum/IR/QuantumTypes.h>
#include <cstddef>
#include <mlir/Dialect/Arith/IR/Arith.h>
#include <mlir/Dialect/Func/IR/FuncOps.h>
Expand Down
11 changes: 4 additions & 7 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
requires = [
"scikit-build-core>=0.12.2",
"setuptools-scm>=9.2.2",
"pennylane-catalyst~=0.14.1",
"pennylane~=0.44.1",
"pennylane-catalyst~=0.15.0",
]
build-backend = "scikit_build_core.build"

Expand Down Expand Up @@ -48,8 +47,7 @@ classifiers = [
requires-python = ">=3.11"
dynamic = ["version"]
dependencies = [
"pennylane-catalyst~=0.14.1",
"pennylane~=0.44.1",
"pennylane-catalyst~=0.15.0",
]

[project.urls]
Expand Down Expand Up @@ -240,7 +238,7 @@ build-frontend = "uv"
[tool.cibuildwheel.linux]
before-all = [
"uv tool install sccache>=0.10.0",
"curl -LsSf https://github.com/munich-quantum-software/setup-mlir/releases/latest/download/setup-mlir.sh | bash -s -- -v 113f01aa82d055410f22a9d03b3468fa68600589 -p /tmp/mlir",
"curl -LsSf https://github.com/munich-quantum-software/setup-mlir/releases/latest/download/setup-mlir.sh | bash -s -- -v 8f264586d7521b0e305ca7bb78825aa3382ffef7 -p /tmp/mlir",
]
environment = { DEPLOY = "ON", PATH="$PATH:/root/.local/bin", MLIR_DIR="/tmp/mlir/lib/cmake/mlir" }
before-test = "uvx sccache --show-stats"
Expand Down Expand Up @@ -286,8 +284,7 @@ exclude = [
build = [
"scikit-build-core>=0.12.2",
"setuptools-scm>=9.2.2",
"pennylane-catalyst~=0.14.1",
"pennylane~=0.44.1",
"pennylane-catalyst~=0.15.0",
]
docs = [
"furo>=2025.12.19",
Expand Down
42 changes: 28 additions & 14 deletions test/test_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@
import pytest
from catalyst.passes import apply_pass

from mqt.core.plugins.catalyst import get_device
from mqt.core.plugins.catalyst import get_catalyst_plugin_abs_path, get_device

if TYPE_CHECKING:
from collections.abc import Generator
from collections.abc import Callable, Generator


# Default pipeline for roundtrip conversion tests
Expand All @@ -50,6 +50,16 @@
MLIR_FILE_TO_CATALYST = "3_AfterToCatalystQuantum.mlir"


def _qjit_with_mqt_plugin(**kwargs: object) -> Callable[[Callable[..., Any]], Any]:
"""Create a qjit decorator that explicitly loads the MQT Catalyst plugin.

Returns:
The configured qjit decorator.
"""
plugin_path = str(get_catalyst_plugin_abs_path())
return qml.qjit(pass_plugins={plugin_path}, dialect_plugins={plugin_path}, **kwargs)


@pytest.fixture(autouse=True)
def _cleanup_mlir_files() -> Generator[None, None, None]:
"""Clean up MLIR files before and after each test to ensure test isolation.
Expand All @@ -73,6 +83,10 @@ def _cleanup_mlir_artifacts() -> None:
for module_dir in mlir_dir.glob("module_*"):
if module_dir.is_dir():
shutil.rmtree(module_dir)
# Remove Catalyst pipeline stage directories created by keep_intermediate.
for stage_dir in mlir_dir.glob("[0-9]_*"):
if stage_dir.is_dir():
shutil.rmtree(stage_dir)
# Remove any loose .mlir files
for mlir_file in mlir_dir.glob("*.mlir"):
mlir_file.unlink()
Expand Down Expand Up @@ -254,7 +268,7 @@ def circuit() -> None:
qml.ctrl(qml.PauliX(wires=0), control=1)
qml.CNOT(wires=[1, 0])

@qml.qjit(target="mlir", pipelines=DEFAULT_PIPELINE, autograph=True, keep_intermediate=2)
@_qjit_with_mqt_plugin(target="mlir", pipelines=DEFAULT_PIPELINE, autograph=True, keep_intermediate=2)
def module() -> Any: # noqa: ANN401
return circuit()

Expand Down Expand Up @@ -302,7 +316,7 @@ def circuit() -> None:
qml.ctrl(qml.PauliY(wires=0), control=1)
qml.CY(wires=[1, 0])

@qml.qjit(target="mlir", pipelines=DEFAULT_PIPELINE, autograph=True, keep_intermediate=2)
@_qjit_with_mqt_plugin(target="mlir", pipelines=DEFAULT_PIPELINE, autograph=True, keep_intermediate=2)
def module() -> Any: # noqa: ANN401
return circuit()

Expand Down Expand Up @@ -350,7 +364,7 @@ def circuit() -> None:
qml.ctrl(qml.PauliZ(wires=0), control=1)
qml.CZ(wires=[1, 0])

@qml.qjit(target="mlir", pipelines=DEFAULT_PIPELINE, autograph=True, keep_intermediate=2)
@_qjit_with_mqt_plugin(target="mlir", pipelines=DEFAULT_PIPELINE, autograph=True, keep_intermediate=2)
def module() -> Any: # noqa: ANN401
return circuit()

Expand Down Expand Up @@ -395,7 +409,7 @@ def circuit() -> None:
qml.ctrl(qml.Hadamard(wires=0), control=1)
qml.CH(wires=[1, 0])

@qml.qjit(target="mlir", pipelines=DEFAULT_PIPELINE, autograph=True, keep_intermediate=2)
@_qjit_with_mqt_plugin(target="mlir", pipelines=DEFAULT_PIPELINE, autograph=True, keep_intermediate=2)
def module() -> Any: # noqa: ANN401
return circuit()

Expand Down Expand Up @@ -434,7 +448,7 @@ def circuit() -> None:
qml.adjoint(qml.S(wires=0))
qml.ctrl(qml.S(wires=0), control=1)

@qml.qjit(target="mlir", pipelines=DEFAULT_PIPELINE, autograph=True, keep_intermediate=2)
@_qjit_with_mqt_plugin(target="mlir", pipelines=DEFAULT_PIPELINE, autograph=True, keep_intermediate=2)
def module() -> Any: # noqa: ANN401
return circuit()

Expand Down Expand Up @@ -472,7 +486,7 @@ def circuit() -> None:
qml.adjoint(qml.T(wires=0))
qml.ctrl(qml.T(wires=0), control=1)

@qml.qjit(target="mlir", pipelines=DEFAULT_PIPELINE, autograph=True, keep_intermediate=2)
@_qjit_with_mqt_plugin(target="mlir", pipelines=DEFAULT_PIPELINE, autograph=True, keep_intermediate=2)
def module() -> Any: # noqa: ANN401
return circuit()

Expand Down Expand Up @@ -512,7 +526,7 @@ def circuit() -> None:
qml.CRX(0.5, wires=[1, 0])
qml.ctrl(qml.CRX(0.5, wires=[1, 0]), control=2)

@qml.qjit(target="mlir", pipelines=DEFAULT_PIPELINE, autograph=True, keep_intermediate=2)
@_qjit_with_mqt_plugin(target="mlir", pipelines=DEFAULT_PIPELINE, autograph=True, keep_intermediate=2)
def module() -> Any: # noqa: ANN401
return circuit()

Expand Down Expand Up @@ -555,7 +569,7 @@ def circuit() -> None:
qml.CRY(0.5, wires=[1, 0])
qml.ctrl(qml.CRY(0.5, wires=[1, 0]), control=2)

@qml.qjit(target="mlir", pipelines=DEFAULT_PIPELINE, autograph=True, keep_intermediate=2)
@_qjit_with_mqt_plugin(target="mlir", pipelines=DEFAULT_PIPELINE, autograph=True, keep_intermediate=2)
def module() -> Any: # noqa: ANN401
return circuit()

Expand Down Expand Up @@ -598,7 +612,7 @@ def circuit() -> None:
qml.CRZ(0.5, wires=[1, 0])
qml.ctrl(qml.CRZ(0.5, wires=[1, 0]), control=2)

@qml.qjit(target="mlir", pipelines=DEFAULT_PIPELINE, autograph=True, keep_intermediate=2)
@_qjit_with_mqt_plugin(target="mlir", pipelines=DEFAULT_PIPELINE, autograph=True, keep_intermediate=2)
def module() -> Any: # noqa: ANN401
return circuit()

Expand Down Expand Up @@ -640,7 +654,7 @@ def circuit() -> None:
qml.ctrl(qml.PhaseShift(0.5, wires=0), control=1)
qml.ControlledPhaseShift(0.5, wires=[1, 0])

@qml.qjit(target="mlir", pipelines=DEFAULT_PIPELINE, autograph=True, keep_intermediate=2)
@_qjit_with_mqt_plugin(target="mlir", pipelines=DEFAULT_PIPELINE, autograph=True, keep_intermediate=2)
def module() -> Any: # noqa: ANN401
return circuit()

Expand Down Expand Up @@ -679,7 +693,7 @@ def circuit() -> None:
qml.ctrl(qml.SWAP(wires=[0, 1]), control=2)
qml.CSWAP(wires=[2, 0, 1])

@qml.qjit(target="mlir", pipelines=DEFAULT_PIPELINE, autograph=True, keep_intermediate=2)
@_qjit_with_mqt_plugin(target="mlir", pipelines=DEFAULT_PIPELINE, autograph=True, keep_intermediate=2)
def module() -> Any: # noqa: ANN401
return circuit()

Expand Down Expand Up @@ -717,7 +731,7 @@ def circuit() -> None:
qml.Toffoli(wires=[0, 1, 2])
qml.ctrl(qml.Toffoli(wires=[0, 1, 2]), control=3)

@qml.qjit(target="mlir", pipelines=DEFAULT_PIPELINE, autograph=True, keep_intermediate=2)
@_qjit_with_mqt_plugin(target="mlir", pipelines=DEFAULT_PIPELINE, autograph=True, keep_intermediate=2)
def module() -> Any: # noqa: ANN401
return circuit()

Expand Down
Loading
Loading