PennyLaneAI / catalyst

A JIT compiler for hybrid quantum programs in PennyLane
https://docs.pennylane.ai/projects/catalyst
Apache License 2.0
138 stars 35 forks source link

Add support for PSWAP and ISWAP gates in the runtime. #395

Closed erick-xanadu closed 9 months ago

erick-xanadu commented 11 months ago

Context

We would like to add support for the PennyLane PSWAP and ISWAP gates to our compilation architecture. Originally, no Catalyst device supported them natively, so they weren't considered, but the Braket plugin which was supported at a later point in time does come with support for them.

Goal

We would like to support the following example without having to rely on decomposition:

import pennylane as qml
from catalyst import *

dev = qml.device("braket.local.qubit", wires=2, shots=100)

@qjit
@qml.qnode(dev)
def f(x: float):
    qml.Hadamard(0)
    qml.PSWAP(x, wires=[0, 1])
    qml.ISWAP(wires=[1, 0])
    return qml.probs()

We can check that right decomposition occurs by inspecting the captured program:

>>> f.jaxpr
{ lambda ; a:f64[]. let
    b:f64[4] = func[
      call_jaxpr={ lambda ; c:f64[]. let
           = qdevice[
            rtd_kwargs={'shots': 100, 'device_type': 'braket.local.qubit', 'backend': 'braket_sv'}
            rtd_lib=/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/catalyst/utils/../lib/librtd_openqasm.dylib
            rtd_name=OpenQasmDevice
          ] 
          d:AbstractQreg() = qalloc 2
          e:AbstractQbit() = qextract d 0
          f:AbstractQbit() = qinst[op=Hadamard qubits_len=1] e
          g:AbstractQbit() = qextract d 1
          h:AbstractQbit() i:AbstractQbit() = qinst[op=SWAP qubits_len=2] f g
          j:AbstractQbit() k:AbstractQbit() = qinst[op=CNOT qubits_len=2] h i
          l:AbstractQbit() = qinst[op=PhaseShift qubits_len=1] k c
          m:AbstractQbit() n:AbstractQbit() = qinst[op=CNOT qubits_len=2] j l
          o:AbstractQbit() = qinst[op=S qubits_len=1] n
          p:AbstractQbit() = qinst[op=S qubits_len=1] m
          q:AbstractQbit() = qinst[op=Hadamard qubits_len=1] o
          r:AbstractQbit() s:AbstractQbit() = qinst[op=CNOT qubits_len=2] q p
          t:AbstractQbit() u:AbstractQbit() = qinst[op=CNOT qubits_len=2] s r
          v:AbstractQbit() = qinst[op=Hadamard qubits_len=1] t
          w:AbstractObs(num_qubits=2,primitive=compbasis) = compbasis v u
          x:f64[4] = probs[shape=(4,)] w
          y:AbstractQreg() = qinsert d 0 v
          z:AbstractQreg() = qinsert y 1 u
           = qdealloc z
        in (x,) }
      fn=<QNode: wires=2, device='braket.local.qubit', interface='auto', diff_method='best'>
    ] a
  in (b,) }

PSWAP and ISWAP are not present, instead we see CNOT, SWAP, and single qubit gates.

Technical details

Generally, Catalyst handles unsupported gates in the Python layer. For this, it relies on the tape expansion mechanism of the device chosen by the user, decomposing any gates not considered "supported". Additionally, Catalyst will also decompose any gates that are unsupported by the compilation pipeline, specifically the QIR interface between compiled program and runtime.

In order to support the new gates, they need to be added in several places:


Note that when installing Catalyst from source, the OpenQASM device is not build by default. Refer to the linked documentation for how to build and test the device.

paul0403 commented 10 months ago

I have updated the four files, and I can build the updated catalyst with make runtime ENABLE_OPENQASM=ON and make frontend successfully. I am fairly certain what I did was correct: I will make a branch for the issue later.

The problem I have is with testing. I am trying to test with

import pennylane as qml
from catalyst import *

dev = qml.device("braket.local.qubit", wires=2, shots=100)

@qjit
@qml.qnode(dev)
def f(x: float):
    qml.Hadamard(0)
    qml.PSWAP(x, wires=[0, 1])
    qml.ISWAP(wires=[1, 0])
    return qml.probs()

and see whether the f.jaxpr still does the decomposition, or does it just call the PSWAP and ISWAP instructions directly.

However, I'm running into an issue with the imports. I cannot seem to import jax on my machine:

>>> import pennylane
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/paul/.local/lib/python3.10/site-packages/pennylane/__init__.py", line 26, in <module>
    import pennylane.numpy
  File "/home/paul/.local/lib/python3.10/site-packages/pennylane/numpy/__init__.py", line 87, in <module>
    from .wrapper import wrap_arrays, extract_tensors, tensor_wrapper
  File "/home/paul/.local/lib/python3.10/site-packages/pennylane/numpy/wrapper.py", line 23, in <module>
    from .tensor import tensor
  File "/home/paul/.local/lib/python3.10/site-packages/pennylane/numpy/tensor.py", line 25, in <module>
    from pennylane.operation import Operator
  File "/home/paul/.local/lib/python3.10/site-packages/pennylane/operation.py", line 256, in <module>
    from pennylane.math import expand_matrix
  File "/home/paul/.local/lib/python3.10/site-packages/pennylane/math/__init__.py", line 37, in <module>
    from .matrix_manipulation import expand_matrix, reduce_matrices, get_batch_size
  File "/home/paul/.local/lib/python3.10/site-packages/pennylane/math/matrix_manipulation.py", line 24, in <module>
    from pennylane.wires import Wires
  File "/home/paul/.local/lib/python3.10/site-packages/pennylane/wires.py", line 21, in <module>
    from pennylane.pytrees import register_pytree
  File "/home/paul/.local/lib/python3.10/site-packages/pennylane/pytrees.py", line 22, in <module>
    import jax.tree_util as jax_tree_util
  File "/home/paul/.local/lib/python3.10/site-packages/jax/__init__.py", line 35, in <module>
    from jax import config as _config_module
  File "/home/paul/.local/lib/python3.10/site-packages/jax/config.py", line 17, in <module>
    from jax._src.config import config  # noqa: F401
  File "/home/paul/.local/lib/python3.10/site-packages/jax/_src/config.py", line 27, in <module>
    from jax._src import lib
  File "/home/paul/.local/lib/python3.10/site-packages/jax/_src/lib/__init__.py", line 84, in <module>
    cpu_feature_guard.check_cpu_features()
RuntimeError: This version of jaxlib was built using AVX instructions, which your CPU and/or operating system do not support. You may be able work around this issue by building jaxlib from source.

Moreover, importing catalyst is even worse:

>>> import catalyst
Illegal instruction (core dumped)

I am working with Linux paul-Standard-PC-Q35-ICH9-2009 6.2.0-39-generic #40~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Nov 16 10:53:04 UTC 2 x86_64 x86_64 x86_64 GNU/Linux (a UTM VM on an Intel i5 MAC). Since the environment is linux x86_64, jax should have no issues. I am a bit confused as to what happened.

The jax and jaxlib version are both 0.4.14, as confirmed by the make frontend script:

install Catalyst Frontend
/usr/bin/python3 -m pip install -e .
Defaulting to user installation because normal site-packages is not writeable
Obtaining file:///home/paul/catalyst
  Installing build dependencies ... done
  Checking if build backend supports build_editable ... done
  Getting requirements to build editable ... done
  Preparing editable metadata (pyproject.toml) ... done
Requirement already satisfied: pennylane>=0.32 in /home/paul/.local/lib/python3.10/site-packages (from PennyLane-Catalyst==0.3.3.dev0) (0.34.0)
Requirement already satisfied: jax==0.4.14 in /home/paul/.local/lib/python3.10/site-packages (from PennyLane-Catalyst==0.3.3.dev0) (0.4.14)
Requirement already satisfied: jaxlib==0.4.14 in /home/paul/.local/lib/python3.10/site-packages (from PennyLane-Catalyst==0.3.3.dev0) (0.4.14)
Requirement already satisfied: scipy in /home/paul/.local/lib/python3.10/site-packages (from PennyLane-Catalyst==0.3.3.dev0) (1.11.4)
Requirement already satisfied: tomlkit in /home/paul/.local/lib/python3.10/site-packages (from PennyLane-Catalyst==0.3.3.dev0) (0.12.3)
Requirement already satisfied: ml-dtypes>=0.2.0 in /home/paul/.local/lib/python3.10/site-packages (from jax==0.4.14->PennyLane-Catalyst==0.3.3.dev0) (0.3.2)
Requirement already satisfied: numpy>=1.22 in /home/paul/.local/lib/python3.10/site-packages (from jax==0.4.14->PennyLane-Catalyst==0.3.3.dev0) (1.26.3)
Requirement already satisfied: opt-einsum in /home/paul/.local/lib/python3.10/site-packages (from jax==0.4.14->PennyLane-Catalyst==0.3.3.dev0) (3.3.0)
Requirement already satisfied: networkx in /home/paul/.local/lib/python3.10/site-packages (from pennylane>=0.32->PennyLane-Catalyst==0.3.3.dev0) (3.2.1)
Requirement already satisfied: rustworkx in /home/paul/.local/lib/python3.10/site-packages (from pennylane>=0.32->PennyLane-Catalyst==0.3.3.dev0) (0.13.2)
Requirement already satisfied: autograd in /home/paul/.local/lib/python3.10/site-packages (from pennylane>=0.32->PennyLane-Catalyst==0.3.3.dev0) (1.6.2)
Requirement already satisfied: toml in /home/paul/.local/lib/python3.10/site-packages (from pennylane>=0.32->PennyLane-Catalyst==0.3.3.dev0) (0.10.2)
Requirement already satisfied: appdirs in /home/paul/.local/lib/python3.10/site-packages (from pennylane>=0.32->PennyLane-Catalyst==0.3.3.dev0) (1.4.4)
Requirement already satisfied: semantic-version>=2.7 in /home/paul/.local/lib/python3.10/site-packages (from pennylane>=0.32->PennyLane-Catalyst==0.3.3.dev0) (2.10.0)
Requirement already satisfied: autoray>=0.6.1 in /home/paul/.local/lib/python3.10/site-packages (from pennylane>=0.32->PennyLane-Catalyst==0.3.3.dev0) (0.6.7)
Requirement already satisfied: cachetools in /home/paul/.local/lib/python3.10/site-packages (from pennylane>=0.32->PennyLane-Catalyst==0.3.3.dev0) (5.3.2)
Requirement already satisfied: pennylane-lightning>=0.34 in /home/paul/.local/lib/python3.10/site-packages (from pennylane>=0.32->PennyLane-Catalyst==0.3.3.dev0) (0.34.0)
Requirement already satisfied: requests in /usr/lib/python3/dist-packages (from pennylane>=0.32->PennyLane-Catalyst==0.3.3.dev0) (2.25.1)
Requirement already satisfied: typing-extensions in /home/paul/.local/lib/python3.10/site-packages (from pennylane>=0.32->PennyLane-Catalyst==0.3.3.dev0) (4.9.0)
Requirement already satisfied: future>=0.15.2 in /usr/lib/python3/dist-packages (from autograd->pennylane>=0.32->PennyLane-Catalyst==0.3.3.dev0) (0.18.2)
Building wheels for collected packages: PennyLane-Catalyst
  Building editable for PennyLane-Catalyst (pyproject.toml) ... done
  Created wheel for PennyLane-Catalyst: filename=PennyLane_Catalyst-0.3.3.dev0-0.editable-cp310-cp310-linux_x86_64.whl size=9512 sha256=edb2f5433622a14020cc6d0df4b1c90d38fbf21427c292b379e10a870f60faf3
  Stored in directory: /tmp/pip-ephem-wheel-cache-mpd9e2ae/wheels/0f/1e/3c/b35aee31d4d6ae2980f5166ef6643177f0887a9c4baef6e6a0
Successfully built PennyLane-Catalyst
Installing collected packages: PennyLane-Catalyst
  Attempting uninstall: PennyLane-Catalyst
    Found existing installation: PennyLane-Catalyst 0.3.3.dev0
    Uninstalling PennyLane-Catalyst-0.3.3.dev0:
      Successfully uninstalled PennyLane-Catalyst-0.3.3.dev0
Successfully installed PennyLane-Catalyst-0.3.3.dev0
rm -r frontend/PennyLane_Catalyst.egg-info

As a workaround I'm trying to build jax from source. Any help would be appreciated. Thanks.

paul0403 commented 10 months ago

Update on the previous problem: building jax and jaxlib from source resolved the "AVX not supported" error but the default build version for jax and jaxlib is 0.4.24 (the current latest as of Jan.13, 2024). Catalyst only supports jax version 0.4.14 exactly, and does not support any higher versions. This might worth looking into.

To resolve this issue, I had to clone the jax repo, switch to an old branch for 0.4.14, and build with the lines in its build script indicating AVX usage commented out. See https://github.com/google/jax/issues/8482

paul0403 commented 10 months ago

BUG: upon a fresh git clone --recurse-submodules --shallow-submodules https://github.com/PennyLaneAI/catalyst.git, the make mlir will fail. This is because in catalyst/mlir/Makefile, we have

all: llvm mhlo enzyme dialects

However, two tests fail for a fresh git-cloned catalyst repo's make llvm:

paul@paul-Standard-PC-Q35-ICH9-2009:~/catalyst/mlir$ make llvm
build LLVM and MLIR enabling Python bindings
cmake -G Ninja -S llvm-project/llvm -B /home/paul/catalyst/mlir//llvm-project/build \
    -DCMAKE_BUILD_TYPE=Release \
    -DLLVM_BUILD_EXAMPLES=OFF \
    -DLLVM_TARGETS_TO_BUILD="host" \
    -DLLVM_ENABLE_PROJECTS="mlir" \
    -DLLVM_ENABLE_ASSERTIONS=ON \
    -DMLIR_ENABLE_BINDINGS_PYTHON=ON \
    -DPython3_EXECUTABLE=/usr/bin/python3 \
    -DPython3_NumPy_INCLUDE_DIRS=$(/usr/bin/python3 -c "import numpy as np; print(np.get_include())") \
    -DCMAKE_C_COMPILER=/usr/bin/clang \
    -DCMAKE_CXX_COMPILER=/usr/bin/clang++ \
    -DCMAKE_C_COMPILER_LAUNCHER=/usr/bin/ccache \
    -DCMAKE_CXX_COMPILER_LAUNCHER=/usr/bin/ccache \
    -DLLVM_USE_SANITIZER="" \
    -DLLVM_ENABLE_LLD=ON \
    -DLLVM_ENABLE_ZLIB=ON \
    -DLLVM_ENABLE_ZSTD=ON
-- bolt project is disabled
-- clang project is disabled
-- clang-tools-extra project is disabled
-- compiler-rt project is disabled
-- cross-project-tests project is disabled
-- libc project is disabled
-- libclc project is disabled
-- lld project is disabled
-- lldb project is disabled
-- mlir project is enabled
-- openmp project is disabled
-- polly project is disabled
-- pstl project is disabled
-- flang project is disabled
-- Found Python3: /usr/bin/python3 (found suitable version "3.10.12", minimum required is "3.6") found components: Interpreter 
-- Could NOT find LibEdit (missing: LibEdit_INCLUDE_DIRS LibEdit_LIBRARIES) 
-- Native target architecture is X86
-- Threads enabled.
-- Doxygen disabled.
-- Ninja version: 1.10.1
-- Could NOT find OCaml (missing: OCAMLFIND OCAML_VERSION OCAML_STDLIB_PATH) 
-- Could NOT find OCaml (missing: OCAMLFIND OCAML_VERSION OCAML_STDLIB_PATH) 
-- OCaml bindings disabled.
-- LLVM host triple: x86_64-unknown-linux-gnu
-- LLVM default target triple: x86_64-unknown-linux-gnu
-- Building with -fPIC
-- Targeting X86
-- Found Python3: /usr/bin/python3 (found suitable version "3.10.12", minimum required is "3.6") found components: Interpreter Development Development.Module Development.Embed 
-- Found Python3: /usr/bin/python3 (found suitable version "3.10.12", minimum required is "3.6") found components: Interpreter Development.Module NumPy 
-- Found python include dirs: /usr/include/python3.10
-- Found python libraries: /usr/lib/x86_64-linux-gnu/libpython3.10.so
-- Found numpy v1.26.3: /home/paul/.local/lib/python3.10/site-packages/numpy/core/include
-- Checking for pybind11 in python path...
-- found (/home/paul/.local/lib/python3.10/site-packages/pybind11/share/cmake/pybind11)
-- Found pybind11: /home/paul/.local/lib/python3.10/site-packages/pybind11/include (found version "2.11.1")
-- Found pybind11 v2.11.1: /home/paul/.local/lib/python3.10/site-packages/pybind11/include
-- Python prefix = '', suffix = '', extension = '.cpython-310-x86_64-linux-gnu.so
-- Registering ExampleIRTransforms as a pass plugin (static build: OFF)
-- Registering Bye as a pass plugin (static build: OFF)
-- LLVM FileCheck Found: /home/paul/catalyst/mlir/llvm-project/build/bin/FileCheck
-- git version: v0.0.0 normalized to 0.0.0
-- Version: 1.6.0
-- Performing Test HAVE_THREAD_SAFETY_ATTRIBUTES -- failed to compile
-- Performing Test HAVE_GNU_POSIX_REGEX -- failed to compile
-- Performing Test HAVE_POSIX_REGEX -- success
-- Performing Test HAVE_STEADY_CLOCK -- success
-- Configuring done
-- Generating done
-- Build files have been written to: /home/paul/catalyst/mlir/llvm-project/build
# TODO: when updating LLVM, test to see if mlir/unittests/Bytecode/BytecodeTest.cpp:55 is passing
# and remove filter
LIT_FILTER_OUT="Bytecode" cmake --build /home/paul/catalyst/mlir//llvm-project/build --target check-mlir llvm-symbolizer
[56/57] Running the MLIR regression tests
FAIL: MLIR :: python/execution_engine.py (1 of 1739)
******************** TEST 'MLIR :: python/execution_engine.py' FAILED ********************
Script:
--
: 'RUN: at line 1';   /usr/bin/python3 /home/paul/catalyst/mlir/llvm-project/mlir/test/python/execution_engine.py 2>&1 | /home/paul/catalyst/mlir/llvm-project/build/bin/FileCheck /home/paul/catalyst/mlir/llvm-project/mlir/test/python/execution_engine.py
--
Exit Code: 1

Command Output (stderr):
--
/home/paul/catalyst/mlir/llvm-project/mlir/test/python/execution_engine.py:341:16: error: CHECK-LABEL: expected string not found in input
# CHECK-LABEL: TEST: testComplexMemrefAdd
               ^
<stdin>:35:23: note: scanning from here
TEST: testF16MemrefAdd
                      ^
<stdin>:37:7: note: possible intended match here
Expected<T> must be checked before access or destruction.
      ^

Input file: <stdin>
Check file: /home/paul/catalyst/mlir/llvm-project/mlir/test/python/execution_engine.py

-dump-input=help explains the following input dump.

Input was:
<<<<<<
             .
             .
             .
            30:  [6. 7.]] 
            31:  
            32: TEST: testMemrefAdd 
            33: [32.5] + 6.0 = [38.5] 
            34:  
            35: TEST: testF16MemrefAdd 
label:341'0                           X error: no match found
            36: JIT session error: Symbols not found: [ __extendhfsf2, __truncsfhf2 ] 
label:341'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            37: Expected<T> must be checked before access or destruction. 
label:341'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
label:341'1           ?                                                    possible intended match
            38: Unchecked Expected<T> contained error: 
label:341'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            39: Failed to materialize symbols: { (main, { _mlir_main, _mlir__mlir_ciface_main, _mlir_ciface_main, main }) }
label:341'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>>>>>

--

********************
FAIL: MLIR :: mlir-cpu-runner/math-polynomial-approx.mlir (2 of 1739)
******************** TEST 'MLIR :: mlir-cpu-runner/math-polynomial-approx.mlir' FAILED ********************
Script:
--
: 'RUN: at line 1';     /home/paul/catalyst/mlir/llvm-project/build/bin/mlir-opt /home/paul/catalyst/mlir/llvm-project/mlir/test/mlir-cpu-runner/math-polynomial-approx.mlir -pass-pipeline="builtin.module(func.func(test-math-polynomial-approximation,convert-arith-to-llvm),convert-vector-to-llvm,func.func(convert-math-to-llvm),convert-func-to-llvm,reconcile-unrealized-casts)"  | /home/paul/catalyst/mlir/llvm-project/build/bin/mlir-cpu-runner                                                           -e main -entry-point-result=void -O0                                    -shared-libs=/home/paul/catalyst/mlir/llvm-project/build/lib/libmlir_c_runner_utils.so       -shared-libs=/home/paul/catalyst/mlir/llvm-project/build/lib/libmlir_runner_utils.so     | /home/paul/catalyst/mlir/llvm-project/build/bin/FileCheck /home/paul/catalyst/mlir/llvm-project/mlir/test/mlir-cpu-runner/math-polynomial-approx.mlir
--
Exit Code: 2

Command Output (stderr):
--
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.  Program arguments: /home/paul/catalyst/mlir/llvm-project/build/bin/mlir-cpu-runner -e main -entry-point-result=void -O0 -shared-libs=/home/paul/catalyst/mlir/llvm-project/build/lib/libmlir_c_runner_utils.so -shared-libs=/home/paul/catalyst/mlir/llvm-project/build/lib/libmlir_runner_utils.so
  #0 0x0000557307ef7e07 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/home/paul/catalyst/mlir/llvm-project/build/bin/mlir-cpu-runner+0x2094e07)
  #1 0x0000557307ef5b3e llvm::sys::RunSignalHandlers() (/home/paul/catalyst/mlir/llvm-project/build/bin/mlir-cpu-runner+0x2092b3e)
  #2 0x0000557307ef873a SignalHandler(int) Signals.cpp:0:0
  #3 0x00007f5087642520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
  #4 0x00007f5087c7e7bb 
  #5 0x00007f5087c7e7fb 
  #6 0x00007f5087c7e7bd 
  #7 0x00007f5087c7e7fb 
  #8 0x00007f5087c7e7bd 
  #9 0x00007f5087c7e7fb 
 #10 0x00007f5087c7e7bd 
 #11 0x00007f5087c7e7fb 
 #12 0x00007f5087c7e7bd 
 #13 0x00007f5087c7e7fb 
 #14 0x00007f5087c7e7bd 
 #15 0x00007f5087c7e7fb 
 #16 0x00007f5087c7e7bd 
 #17 0x00007f5087c7e7fb 
 #18 0x00007f5087c7e7bd 
 #19 0x00007f5087c7e7fb 
 #20 0x00007f5087c7e7bd 
 #21 0x00007f5087c7e7fb 
 #22 0x00007f5087c7e7bd 
 #23 0x00007f5087c7e7fb 
 #24 0x00007f5087c7e7bd 
 #25 0x00007f5087c7e7fb 
 #26 0x00007f5087c7e7bd 
 #27 0x00007f5087c7e7fb 
 #28 0x00007f5087c7e7bd 
 #29 0x00007f5087c7e7fb 
 #30 0x00007f5087c7e7bd 
 #31 0x00007f5087c7e7fb 
 #32 0x00007f5087c7e7bd 
 #33 0x00007f5087c7e7fb 
 #34 0x00007f5087c7e7bd 
 #35 0x00007f5087c7e7fb 
 #36 0x00007f5087c7e7bd 
 #37 0x00007f5087c7e7fb 
 #38 0x00007f5087c7e7bd 
 #39 0x00007f5087c7e7fb 
 #40 0x00007f5087c7e7bd 
 #41 0x00007f5087c7e7fb 
 #42 0x00007f5087c7e7bd 
 #43 0x00007f5087c7e7fb 
 #44 0x00007f5087c7e7bd 
 #45 0x00007f5087c7e7fb 
 #46 0x00007f5087c7e7bd 
 #47 0x00007f5087c7e7fb 
 #48 0x00007f5087c7e7bd 
 #49 0x00007f5087c7e7fb 
 #50 0x00007f5087c7e7bd 
 #51 0x00007f5087c7e7fb 
 #52 0x00007f5087c7e7bd 
 #53 0x00007f5087c7e7fb 
 #54 0x00007f5087c7e7bd 
 #55 0x00007f5087c7e7fb 
 #56 0x00007f5087c7e7bd 
 #57 0x00007f5087c7e7fb 
 #58 0x00007f5087c7e7bd 
 #59 0x00007f5087c7e7fb 
 #60 0x00007f5087c7e7bd 
 #61 0x00007f5087c7e7fb 
 #62 0x00007f5087c7e7bd 
 #63 0x00007f5087c7e7fb 
 #64 0x00007f5087c7e7bd 
 #65 0x00007f5087c7e7fb 
 #66 0x00007f5087c7e7bd 
 #67 0x00007f5087c7e7fb 
 #68 0x00007f5087c7e7bd 
 #69 0x00007f5087c7e7fb 
 #70 0x00007f5087c7e7bd 
 #71 0x00007f5087c7e7fb 
 #72 0x00007f5087c7e7bd 
 #73 0x00007f5087c7e7fb 
 #74 0x00007f5087c7e7bd 
 #75 0x00007f5087c7e7fb 
 #76 0x00007f5087c7e7bd 
 #77 0x00007f5087c7e7fb 
 #78 0x00007f5087c7e7bd 
 #79 0x00007f5087c7e7fb 
 #80 0x00007f5087c7e7bd 
 #81 0x00007f5087c7e7fb 
 #82 0x00007f5087c7e7bd 
 #83 0x00007f5087c7e7fb 
 #84 0x00007f5087c7e7bd 
 #85 0x00007f5087c7e7fb 
 #86 0x00007f5087c7e7bd 
 #87 0x00007f5087c7e7fb 
 #88 0x00007f5087c7e7bd 
 #89 0x00007f5087c7e7fb 
 #90 0x00007f5087c7e7bd 
 #91 0x00007f5087c7e7fb 
 #92 0x00007f5087c7e7bd 
 #93 0x00007f5087c7e7fb 
 #94 0x00007f5087c7e7bd 
 #95 0x00007f5087c7e7fb 
 #96 0x00007f5087c7e7bd 
 #97 0x00007f5087c7e7fb 
 #98 0x00007f5087c7e7bd 
 #99 0x00007f5087c7e7fb 
#100 0x00007f5087c7e7bd 
#101 0x00007f5087c7e7fb 
#102 0x00007f5087c7e7bd 
#103 0x00007f5087c7e7fb 
#104 0x00007f5087c7e7bd 
#105 0x00007f5087c7e7fb 
#106 0x00007f5087c7e7bd 
#107 0x00007f5087c7e7fb 
#108 0x00007f5087c7e7bd 
#109 0x00007f5087c7e7fb 
#110 0x00007f5087c7e7bd 
#111 0x00007f5087c7e7fb 
#112 0x00007f5087c7e7bd 
#113 0x00007f5087c7e7fb 
#114 0x00007f5087c7e7bd 
#115 0x00007f5087c7e7fb 
#116 0x00007f5087c7e7bd 
#117 0x00007f5087c7e7fb 
#118 0x00007f5087c7e7bd 
#119 0x00007f5087c7e7fb 
#120 0x00007f5087c7e7bd 
#121 0x00007f5087c7e7fb 
#122 0x00007f5087c7e7bd 
#123 0x00007f5087c7e7fb 
#124 0x00007f5087c7e7bd 
#125 0x00007f5087c7e7fb 
#126 0x00007f5087c7e7bd 
#127 0x00007f5087c7e7fb 
#128 0x00007f5087c7e7bd 
#129 0x00007f5087c7e7fb 
#130 0x00007f5087c7e7bd 
#131 0x00007f5087c7e7fb 
#132 0x00007f5087c7e7bd 
#133 0x00007f5087c7e7fb 
#134 0x00007f5087c7e7bd 
#135 0x00007f5087c7e7fb 
#136 0x00007f5087c7e7bd 
#137 0x00007f5087c7e7fb 
#138 0x00007f5087c7e7bd 
#139 0x00007f5087c7e7fb 
#140 0x00007f5087c7e7bd 
#141 0x00007f5087c7e7fb 
#142 0x00007f5087c7e7bd 
#143 0x00007f5087c7e7fb 
#144 0x00007f5087c7e7bd 
#145 0x00007f5087c7e7fb 
#146 0x00007f5087c7e7bd 
#147 0x00007f5087c7e7fb 
#148 0x00007f5087c7e7bd 
#149 0x00007f5087c7e7fb 
#150 0x00007f5087c7e7bd 
#151 0x00007f5087c7e7fb 
#152 0x00007f5087c7e7bd 
#153 0x00007f5087c7e7fb 
#154 0x00007f5087c7e7bd 
#155 0x00007f5087c7e7fb 
#156 0x00007f5087c7e7bd 
#157 0x00007f5087c7e7fb 
#158 0x00007f5087c7e7bd 
#159 0x00007f5087c7e7fb 
#160 0x00007f5087c7e7bd 
#161 0x00007f5087c7e7fb 
#162 0x00007f5087c7e7bd 
#163 0x00007f5087c7e7fb 
#164 0x00007f5087c7e7bd 
#165 0x00007f5087c7e7fb 
#166 0x00007f5087c7e7bd 
#167 0x00007f5087c7e7fb 
#168 0x00007f5087c7e7bd 
#169 0x00007f5087c7e7fb 
#170 0x00007f5087c7e7bd 
#171 0x00007f5087c7e7fb 
#172 0x00007f5087c7e7bd 
#173 0x00007f5087c7e7fb 
#174 0x00007f5087c7e7bd 
#175 0x00007f5087c7e7fb 
#176 0x00007f5087c7e7bd 
#177 0x00007f5087c7e7fb 
#178 0x00007f5087c7e7bd 
#179 0x00007f5087c7e7fb 
#180 0x00007f5087c7e7bd 
#181 0x00007f5087c7e7fb 
#182 0x00007f5087c7e7bd 
#183 0x00007f5087c7e7fb 
#184 0x00007f5087c7e7bd 
#185 0x00007f5087c7e7fb 
#186 0x00007f5087c7e7bd 
#187 0x00007f5087c7e7fb 
#188 0x00007f5087c7e7bd 
#189 0x00007f5087c7e7fb 
#190 0x00007f5087c7e7bd 
#191 0x00007f5087c7e7fb 
#192 0x00007f5087c7e7bd 
#193 0x00007f5087c7e7fb 
#194 0x00007f5087c7e7bd 
#195 0x00007f5087c7e7fb 
#196 0x00007f5087c7e7bd 
#197 0x00007f5087c7e7fb 
#198 0x00007f5087c7e7bd 
#199 0x00007f5087c7e7fb 
#200 0x00007f5087c7e7bd 
#201 0x00007f5087c7e7fb 
#202 0x00007f5087c7e7bd 
#203 0x00007f5087c7e7fb 
#204 0x00007f5087c7e7bd 
#205 0x00007f5087c7e7fb 
#206 0x00007f5087c7e7bd 
#207 0x00007f5087c7e7fb 
#208 0x00007f5087c7e7bd 
#209 0x00007f5087c7e7fb 
#210 0x00007f5087c7e7bd 
#211 0x00007f5087c7e7fb 
#212 0x00007f5087c7e7bd 
#213 0x00007f5087c7e7fb 
#214 0x00007f5087c7e7bd 
#215 0x00007f5087c7e7fb 
#216 0x00007f5087c7e7bd 
#217 0x00007f5087c7e7fb 
#218 0x00007f5087c7e7bd 
#219 0x00007f5087c7e7fb 
#220 0x00007f5087c7e7bd 
#221 0x00007f5087c7e7fb 
#222 0x00007f5087c7e7bd 
#223 0x00007f5087c7e7fb 
#224 0x00007f5087c7e7bd 
#225 0x00007f5087c7e7fb 
#226 0x00007f5087c7e7bd 
#227 0x00007f5087c7e7fb 
#228 0x00007f5087c7e7bd 
#229 0x00007f5087c7e7fb 
#230 0x00007f5087c7e7bd 
#231 0x00007f5087c7e7fb 
#232 0x00007f5087c7e7bd 
#233 0x00007f5087c7e7fb 
#234 0x00007f5087c7e7bd 
#235 0x00007f5087c7e7fb 
#236 0x00007f5087c7e7bd 
#237 0x00007f5087c7e7fb 
#238 0x00007f5087c7e7bd 
#239 0x00007f5087c7e7fb 
#240 0x00007f5087c7e7bd 
#241 0x00007f5087c7e7fb 
#242 0x00007f5087c7e7bd 
#243 0x00007f5087c7e7fb 
#244 0x00007f5087c7e7bd 
#245 0x00007f5087c7e7fb 
#246 0x00007f5087c7e7bd 
#247 0x00007f5087c7e7fb 
#248 0x00007f5087c7e7bd 
#249 0x00007f5087c7e7fb 
#250 0x00007f5087c7e7bd 
#251 0x00007f5087c7e7fb 
#252 0x00007f5087c7e7bd 
#253 0x00007f5087c7e7fb 
#254 0x00007f5087c7e7bd 
#255 0x00007f5087c7e7fb 
FileCheck error: '<stdin>' is empty.
FileCheck command line:  /home/paul/catalyst/mlir/llvm-project/build/bin/FileCheck /home/paul/catalyst/mlir/llvm-project/mlir/test/mlir-cpu-runner/math-polynomial-approx.mlir

--

********************
********************
Failed Tests (2):
  MLIR :: mlir-cpu-runner/math-polynomial-approx.mlir
  MLIR :: python/execution_engine.py

Testing Time: 197.60s
  Excluded   :   21
  Unsupported:  344
  Passed     : 1852
  Failed     :    2
FAILED: tools/mlir/test/CMakeFiles/check-mlir /home/paul/catalyst/mlir/llvm-project/build/tools/mlir/test/CMakeFiles/check-mlir 
cd /home/paul/catalyst/mlir/llvm-project/build/tools/mlir/test && /usr/bin/python3 /home/paul/catalyst/mlir/llvm-project/build/./bin/llvm-lit -sv /home/paul/catalyst/mlir/llvm-project/build/tools/mlir/test
ninja: build stopped: subcommand failed.
make: *** [Makefile:59: llvm] Error 1

So the three later targets are never built, since the makefile is interrupted by this error. At the python frontend the syndrome is when one tries to import catalyst, one gets the ModuleNotFoundError: No module named 'mlir_quantum' error (which makes sense: the module was never built).

Currently I am working around this by building all 4 targets by hand. In this fashion even if some tests failed the built binaries will still be there. The three later targets (mhlo, enzyme and dialects) does not produce any failed tests.

Please look into why a fresh build has failed tests.

paul0403 commented 10 months ago

After building all the mlir targets one by one by hand, I was able to import catalyst. However a new problem arises: seems like the jax without AVX just won't work with catalyst. A simple dev=qml.device("default.qubit") will encounter errors:

>>> import pennylane as qml
>>> from catalyst import *
>>> dev = qml.device("default.qubit")
>>> @qjit
... @qml.qnode(dev)
... def f():
...    qml.Hadamard(0)
...    return qml.probs()
... 
Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
  File "/home/paul/catalyst/frontend/catalyst/compilation_pipelines.py", line 1052, in qjit
    return QJIT(
  File "/home/paul/catalyst/frontend/catalyst/compilation_pipelines.py", line 530, in __init__
    self.mlir_module = self.get_mlir(*parameter_types)
  File "/home/paul/catalyst/frontend/catalyst/compilation_pipelines.py", line 580, in get_mlir
    mlir_module, ctx, jaxpr, _, self.out_tree = trace_to_mlir(func, abstracted_axes, *sig)
  File "/home/paul/catalyst/frontend/catalyst/jax_tracer.py", line 352, in trace_to_mlir
    jaxpr, out_type, out_tree = make_jaxpr2(func, **make_jaxpr_kwargs)(*args, **kwargs)
  File "/home/paul/catalyst/frontend/catalyst/utils/jax_extras.py", line 474, in make_jaxpr_f
    jaxpr, out_type, consts = trace_to_jaxpr_dynamic2(f)
  File "/home/paul/jax/jax/_src/profiler.py", line 314, in wrapper
    return func(*args, **kwargs)
  File "/home/paul/jax/jax/_src/interpreters/partial_eval.py", line 2191, in trace_to_jaxpr_dynamic2
    jaxpr, out_type, consts = trace_to_subjaxpr_dynamic2(fun, main, debug_info)
  File "/home/paul/jax/jax/_src/interpreters/partial_eval.py", line 2206, in trace_to_subjaxpr_dynamic2
    ans = fun.call_wrapped(*in_tracers_)
  File "/home/paul/jax/jax/_src/linear_util.py", line 188, in call_wrapped
    ans = self.f(*args, **dict(self.params, **kwargs))
  File "/home/paul/catalyst/frontend/catalyst/pennylane_extensions.py", line 152, in __call__
    dev_args = extract_backend_info(self.device)
  File "/home/paul/catalyst/frontend/catalyst/utils/runtime.py", line 232, in extract_backend_info
    validate_config_with_device(device)
  File "/home/paul/catalyst/frontend/catalyst/utils/runtime.py", line 220, in validate_config_with_device
    check_device_config(device)
  File "/home/paul/catalyst/frontend/catalyst/utils/runtime.py", line 91, in check_device_config
    raise CompileError(msg)
catalyst.utils.exceptions.CompileError: Attempting to compile program for incompatible device default.qubit.

So I guess whatever machine I'm using that doesn't have AVX is just hopeless for catalyst.

As an alternative, my school (UofT) does have remote Ubuntu x86_64 machines I can ssh into. I can run the sample program in the issue (in the "Goal" section) with the released version of catalyst (aka the pip install pennylane-catalyst one, which grabs jax and jaxlib 0.4.14) and obtain the same output program as listed in the issue. However these machines do not have lld and so currently I cannot build my changed version (the one with PSWAP and ISWAP in the above commit) from source. I will contact the system admin and get it to work on these machines.

josh146 commented 10 months ago

Hey @paul0403! If you can't get the source installation to work locally, developing via a PR directly on github here would be an okay workaround -- the CI checks on the PR will run the test suite with each commit, ensuring all tests are passing.

paul0403 commented 10 months ago

Hey @paul0403! If you can't get the source installation to work locally, developing via a PR directly on github here would be an okay workaround -- the CI checks on the PR will run the test suite with each commit, ensuring all tests are passing.

Hi @josh146 , on the PR I created, most of the CI checks are stuck on "expected — Waiting for status to be reported", with "This workflow requires approval from a maintainer.". Apparently every time I commit someone from the catalyst team needs to manually approve to run the CI checks. Is there any way I can do the checks from my end? Thanks.

paul0403 commented 10 months ago

@josh146 I just made some changes. Please run CI again. Thanks

josh146 commented 10 months ago

Done!

paul0403 commented 10 months ago

@josh146 I just made some changes. Please run CI again. Thanks.

paul0403 commented 10 months ago

All the feature functionality pipelines have passed (yay). The three failed tests are readthedocs, c++ formatting, and Check Catalyst Build / Runtime Code Coverage (Linux) (pull_request). The first two are easily fixable by me. For the last one, the report is at https://github.com/PennyLaneAI/catalyst/actions/runs/7531845654/job/20501338908?pr=458

Seems like there was some issue uploading to codecov to generate a report and this would be unfixable from my end. Fortunately the codecov one doesn't come with the required tag so it's not urgent.

I'll fix the format and documentation in a bit.

paul0403 commented 10 months ago

@josh146 I just made some changes. Please run CI again. Thanks.

I fixed the C++ formatting and squashed the previous commits. This run is supposed to pass all functional feature CIs and the C++ formatting CI.

The readthedocs CI seems unfixable from my end: the report says the sphinx version in the CI is not high enough.

paul0403 commented 10 months ago

@josh146 I just made some changes. Please run CI again. Thanks.

Fixing a typo

paul0403 commented 10 months ago

It is with great pleasure that I report that I have resolved the "AVX not supported" error! Turns out when setting up my VM with UTM on my macbook, UTM's default CPU option just happened to choose an intel processor that does not support AVX instructions, causing all the troubles. I have manually specified a cpu with avx support. I can finally run catalyst! I tested with a freshly pip install pennylane-catalyst, i.e. the stable release version, and it happily gives me

import pennylane as qml
from catalyst import *

dev = qml.device("lightning.qubit", wires=2, shots=100)

@qjit
@qml.qnode(dev)
def f():
    qml.Hadamard(0)
    return qml.probs()   # should be (|00> + |10>)/sqrt(2)

f() # gives me something like array([0.51, 0.  , 0.49, 0.  ])
f.jaxpr 
# gives me
{ lambda ; . let
    a:f64[4] = func[
      call_jaxpr={ lambda ; . let
           = qdevice[
            rtd_kwargs={'shots': 100, 'mcmc': False}
            rtd_lib=/home/paul/.local/lib/python3.10/site-packages/catalyst/utils/../lib/librtd_lightning.so
            rtd_name=LightningSimulator
          ] 
          b:AbstractQreg() = qalloc 2
          c:AbstractQbit() = qextract b 0
          d:AbstractQbit() = qinst[op=Hadamard qubits_len=1] c
          e:AbstractQbit() = qextract b 1
          f:AbstractObs(num_qubits=2,primitive=compbasis) = compbasis d e
          g:f64[4] = probs[shape=(4,)] f
          h:AbstractQreg() = qinsert b 0 d
           = qdealloc h
        in (g,) }
      fn=<QNode: wires=2, device='lightning.qubit', interface='auto', diff_method='best'>
    ] 
  in (a,) }

As a lucky bonus, the failed tests when make mlir also went away.

Take home lesson: choose an intel i5 (or higher) cpu for catalyst. For the record, the one I chose is Intel Core Processor (Skylake) (Skylake-Client-v1).

paul0403 commented 10 months ago

@josh146 Apparently I'm having some trouble installing the OpenQasm device. From my branch in the PR I built catalyst with

# In top-level directory catalyst
make runtime ENABLE_OPENQASM=ON
make mlir
make frontend

My test file is located at catalyst/hi.py in the top level catalyst directory:

import pennylane as qml
from catalyst import *

dev = qml.device("braket.local.qubit", wires=2, shots=100)
#dev = qml.device("lightning.qubit", wires=2, shots=100)
#dev = qml.device("default.qubit", wires=2, shots=100)

@qjit
@qml.qnode(dev)
def f(x:float):
   qml.Hadamard(0)
   qml.PSWAP(x, wires=[0,1])
   qml.ISWAP(wires=[1,0])
   return qml.probs()

print(f(0))
print(f.jaxpr)

With braket.local.qubit, I still get pennylane._device.DeviceError: Device braket.local.qubit does not exist. Make sure the required plugin is installed. However with lightning.qubit I get the expected output

[0.55 0.   0.45 0.  ]
{ lambda ; a:f64[]. let
    b:f64[4] = func[
      call_jaxpr={ lambda ; c:f64[]. let
           = qdevice[
            rtd_kwargs={'shots': 100, 'mcmc': False}
            rtd_lib=/home/paul/catalyst/runtime/build/lib/librtd_lightning.so
            rtd_name=LightningSimulator
          ] 
          d:AbstractQreg() = qalloc 2
          e:AbstractQbit() = qextract d 0
          f:AbstractQbit() = qinst[op=Hadamard qubits_len=1] e
          g:AbstractQbit() = qextract d 1
          h:AbstractQbit() i:AbstractQbit() = qinst[op=SWAP qubits_len=2] f g
          j:AbstractQbit() k:AbstractQbit() = qinst[op=CNOT qubits_len=2] h i
          l:AbstractQbit() = qinst[op=PhaseShift qubits_len=1] k c
          m:AbstractQbit() n:AbstractQbit() = qinst[op=CNOT qubits_len=2] j l
          o:AbstractQbit() = qinst[op=S qubits_len=1] n
          p:AbstractQbit() = qinst[op=S qubits_len=1] m
          q:AbstractQbit() = qinst[op=Hadamard qubits_len=1] o
          r:AbstractQbit() s:AbstractQbit() = qinst[op=CNOT qubits_len=2] q p
          t:AbstractQbit() u:AbstractQbit() = qinst[op=CNOT qubits_len=2] s r
          v:AbstractQbit() = qinst[op=Hadamard qubits_len=1] t
          w:AbstractObs(num_qubits=2,primitive=compbasis) = compbasis v u
          x:f64[4] = probs[shape=(4,)] w
          y:AbstractQreg() = qinsert d 0 v
          z:AbstractQreg() = qinsert y 1 u
           = qdealloc z
        in (x,) }
      fn=<QNode: wires=2, device='lightning.qubit', interface='auto', diff_method='best'>
    ] a
  in (b,) }

(Notice the PSWAP and ISWAP are still decomposed as CNOTs and SWAPs, as their support is only added to openqasm, not the lightning.qubit)

Did I miss anything in the installation? I did build with make runtime ENABLE_OPENQASM=ON, and the binary runtime/build/lib/librtd_openqasm.so does exist.

maliasadi commented 10 months ago

Hi @paul0403, thank you for working on this issue! :tada:

Regarding the issue with testing the support:

pennylane._device.DeviceError: Device braket.local.qubit does not exist. Make sure the required plugin is installed.

This is a PennyLane error message raising that the amazon-braket-pennylane-plugin package is not installed on your system. You can install the package either via installing the entire dev requirements in Catalyst:

python -m pip install -r requirements.txt

Or, separately from pypi python -m pip install amazon-braket-pennylane-plugin.

You can test all braket end-to-end tests using the following Make command:

make test-frontend TEST_BRAKET=LOCAL

Please don't hesitate to reach out if there are any questions or issues.

paul0403 commented 10 months ago

@maliasadi Hi Ali, thanks for the help! I completely missed the requirement.txt!

With amazon-braket plugin installed, this commit can now achieve its goal. Here's a small test I just ran:

import pennylane as qml
from catalyst import *

dev = qml.device("braket.local.qubit", wires=2, shots=100)

@qjit
@qml.qnode(dev)
def h():
   qml.ISWAP(wires=[0,1])
   qml.PSWAP(1.23, wires=[0,1])  # some randomly picked angle phi
   return qml.probs()

This program now gives

>>> h()
array([1., 0., 0., 0.])
>>> h.jaxpr
{ lambda ; . let
    a:f64[4] = func[
      call_jaxpr={ lambda ; . let
           = qdevice[
            rtd_kwargs={'shots': 100, 'device_type': 'braket.local.qubit', 'backend': 'braket_sv'}
            rtd_lib=/home/paul/catalyst/frontend/catalyst/utils/../../../runtime/build/lib/librtd_openqasm.so
            rtd_name=OpenQasmDevice
          ] 
          b:AbstractQreg() = qalloc 2
          c:AbstractQbit() = qextract b 0
          d:AbstractQbit() = qextract b 1
          e:AbstractQbit() f:AbstractQbit() = qinst[op=ISWAP qubits_len=2] c d
          g:AbstractQbit() h:AbstractQbit() = qinst[op=PSWAP qubits_len=2] e f 1.23
          i:AbstractObs(num_qubits=2,primitive=compbasis) = compbasis g h
          j:f64[4] = probs[shape=(4,)] i
          k:AbstractQreg() = qinsert b 0 g
          l:AbstractQreg() = qinsert k 1 h
           = qdealloc l
        in (j,) }
      fn=<QNode: wires=2, device='braket.local.qubit', interface='auto', diff_method='best'>
    ] 
  in (a,) }

which is expected! The functionality passes a first-impression sanity check since both gates leave |00> invariant, so the probability returned should be [1,0,0,0], and indeed it is. Also the program now no longer decomposes the ISWAP and PSWAP gates into other gates. It just calls the ISWAP and PSWAP quantum instructions from the librtd_openqasm.so directly, which was the goal of this issue!

I have class in a bit so I will answer the questions on the PR and write unit tests at a later time!

paul0403 commented 10 months ago

@josh146 I just made some changes. Please run CI again. Thanks.

paul0403 commented 10 months ago

@josh146 I just made some changes. Please run CI again. Thanks.

paul0403 commented 10 months ago

@josh146 I just made some changes. Please run CI again. Thanks.

josh146 commented 9 months ago

Will do. @paul0403 I recommend going forward commenting on the PR, rather than the issue 🙂