diff --git a/.github/workflows/build-wheel-linux-x86_64.yaml b/.github/workflows/build-wheel-linux-x86_64.yaml index faf0a8e88e..faf2eb1681 100644 --- a/.github/workflows/build-wheel-linux-x86_64.yaml +++ b/.github/workflows/build-wheel-linux-x86_64.yaml @@ -277,7 +277,7 @@ jobs: - name: Install Dependencies (Python) run: | - python${{ matrix.python_version }} -m pip install numpy pybind11 PyYAML cmake ninja + python${{ matrix.python_version }} -m pip install numpy pybind11 scipy PyYAML cmake ninja # Add cmake and ninja to the PATH env var PYTHON_BINS=$(find /opt/_internal/cpython-${{ matrix.python_version }}.*/bin -maxdepth 1 -type d | tr '\n' ':' | sed 's/:$//') echo $PYTHON_BINS >> $GITHUB_PATH @@ -340,6 +340,9 @@ jobs: -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=$GITHUB_WORKSPACE/runtime-build/lib \ -DPYTHON_EXECUTABLE=$(which python${{ matrix.python_version }}) \ + -DUSE_PYTHON_HEADERS=ON \ + -DPYTHON_INCLUDE_DIR=$(python${{ matrix.python_version }} -c "from distutils.sysconfig import get_python_inc; print(get_python_inc())") \ + -DPYTHON_LIBRARY=$(python3${{ matrix.python_version }} -c "import sysconfig; import os; print(os.path.join(sysconfig.get_config_var('LIBDIR'), sysconfig.get_config_var('LIBRARY')))") \ -Dpybind11_DIR=$(python${{ matrix.python_version }} -c "import pybind11; print(pybind11.get_cmake_dir())") \ -DENABLE_OPENQASM=ON diff --git a/.github/workflows/build-wheel-macos-arm64.yaml b/.github/workflows/build-wheel-macos-arm64.yaml index 01c9045160..702a9f6c20 100644 --- a/.github/workflows/build-wheel-macos-arm64.yaml +++ b/.github/workflows/build-wheel-macos-arm64.yaml @@ -132,7 +132,7 @@ jobs: - name: Install Dependencies (Python) run: | - python${{ matrix.python_version }} -m pip install numpy pybind11 PyYAML cmake ninja + python${{ matrix.python_version }} -m pip install numpy pybind11 scipy PyYAML cmake ninja - name: Build LLVM / MLIR if: steps.cache-llvm-build.outputs.cache-hit != 'true' diff --git a/.github/workflows/build-wheel-macos-x86_64.yaml b/.github/workflows/build-wheel-macos-x86_64.yaml index 853cb1390c..3254f1fe9b 100644 --- a/.github/workflows/build-wheel-macos-x86_64.yaml +++ b/.github/workflows/build-wheel-macos-x86_64.yaml @@ -230,7 +230,7 @@ jobs: - name: Install Dependencies (Python) run: | - python${{ matrix.python_version }} -m pip install numpy pybind11 PyYAML cmake ninja delocate + python${{ matrix.python_version }} -m pip install numpy pybind11 scipy PyYAML cmake ninja delocate - name: Get Cached LLVM Source id: cache-llvm-source diff --git a/.github/workflows/check-catalyst.yaml b/.github/workflows/check-catalyst.yaml index 2361365270..b2d709fe19 100644 --- a/.github/workflows/check-catalyst.yaml +++ b/.github/workflows/check-catalyst.yaml @@ -127,7 +127,7 @@ jobs: sudo apt-get update sudo apt-get install -y python3 python3-pip cmake ninja-build clang lld python3 --version | grep ${{ needs.constants.outputs.primary_python_version }} - python3 -m pip install numpy pybind11 + python3 -m pip install numpy pybind11 scipy - name: Build LLVM if: steps.cache-llvm-build.outputs.cache-hit != 'true' @@ -299,7 +299,7 @@ jobs: sudo apt-get update sudo apt-get install -y python3 python3-pip cmake ninja-build ccache clang lld python3 --version | grep ${{ needs.constants.outputs.primary_python_version }} - python3 -m pip install numpy pybind11 + python3 -m pip install numpy pybind11 scipy - name: Get Cached LLVM Source id: cache-llvm-source @@ -407,6 +407,7 @@ jobs: sudo apt-get install -y python3 python3-pip libomp-dev libasan6 make ninja-build python3 --version | grep ${{ needs.constants.outputs.primary_python_version }} python3 -m pip install -r requirements.txt + python3 -m pip install scipy # cuda-quantum is added manually here. # It can't be in requirements.txt as that will break # macOS requirements.txt @@ -597,7 +598,8 @@ jobs: - name: Install dependencies run: | sudo apt-get update - sudo apt-get -y -q install cmake ninja-build libomp-dev lcov libasan6 + sudo apt-get -y -q install python3 python3-pip cmake ninja-build libomp-dev lcov libasan6 + python3 -m pip install scipy - name: Install additional dependencies (OpenQasm device) if: ${{ matrix.backend == 'openqasm' }} @@ -663,7 +665,8 @@ jobs: - name: Install dependencies run: | sudo apt-get update - sudo apt-get -y -q install cmake ninja-build libomp-dev lcov + sudo apt-get -y -q install python3 python3-pip cmake ninja-build libomp-dev lcov + python3 -m pip install scipy - name: Build Runtime test suite for Lightning simulator run: | diff --git a/Makefile b/Makefile index b2524c3b64..6a632c0568 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -PYTHON ?= $(shell which python3) +PYTHON ?= $(shell which python) C_COMPILER ?= $(shell which clang) CXX_COMPILER ?= $(shell which clang++) BLACKVERSIONMAJOR := $(shell black --version 2> /dev/null | head -n1 | awk '{ print $$2 }' | cut -d. -f1) @@ -241,6 +241,7 @@ coverage: coverage-frontend coverage-runtime coverage-frontend: @echo "Generating coverage report for the frontend" + $(ASAN_COMMAND) $(PYTHON) -m pip install scipy $(ASAN_COMMAND) $(PYTHON) -m pytest frontend/test/pytest $(PARALLELIZE) --cov=catalyst --tb=native --cov-report=$(COVERAGE_REPORT) $(ASAN_COMMAND) $(PYTHON) -m pytest frontend/test/test_oqc/oqc $(PARALLELIZE) --cov=catalyst --cov-append --tb=native --cov-report=$(COVERAGE_REPORT) ifeq ($(TEST_BRAKET), NONE) diff --git a/frontend/test/pytest/test_measurements_shots_results.py b/frontend/test/pytest/test_measurements_shots_results.py index 0157373827..adde75e4c8 100644 --- a/frontend/test/pytest/test_measurements_shots_results.py +++ b/frontend/test/pytest/test_measurements_shots_results.py @@ -124,11 +124,13 @@ def circuit(): result = qjit(circuit)() assert np.allclose(result, expected, atol=tol_stochastic, rtol=tol_stochastic) - def test_hermitian(self, backend): + def test_hermitian(self, backend, tol_stochastic): """Test expval Hermitian observables with shots.""" + n_wires = 3 + n_shots = 10000 + dev = qml.device(backend, wires=n_wires, shots=n_shots) - @qjit - @qml.qnode(qml.device(backend, wires=3, shots=10000)) + @qml.qnode(dev) def circuit(x, y): qml.RX(x, wires=0) qml.RX(y, wires=1) @@ -136,13 +138,12 @@ def circuit(x, y): A = np.array( [[complex(1.0, 0.0), complex(2.0, 0.0)], [complex(2.0, 0.0), complex(1.0, 0.0)]] ) - return qml.expval(qml.Hermitian(A, wires=2) + qml.PauliX(0) + qml.Hermitian(A, wires=1)) + return qml.expval(qml.Hermitian(A, wires=2)) - with pytest.raises( - RuntimeError, - match="Hermitian observables with shot measurement are not supported", - ): - circuit(np.pi / 4, np.pi / 4) + expected = circuit(np.pi / 4, np.pi / 4) + result = qjit(circuit)(np.pi / 4, np.pi / 4) + + assert np.allclose(result, expected, atol=tol_stochastic, rtol=tol_stochastic) def test_paulix_pauliy(self, backend, tol_stochastic): """Test that a tensor product involving PauliX and PauliY works correctly""" @@ -332,11 +333,13 @@ def circuit(): result = qjit(circuit)() assert np.allclose(result, expected, atol=tol_stochastic, rtol=tol_stochastic) - def test_hermitian_shots(self, backend): + def test_hermitian_shots(self, backend, tol_stochastic): """Test var Hermitian observables with shots.""" + n_wires = 3 + n_shots = 10000 + dev = qml.device(backend, wires=n_wires, shots=n_shots) - @qjit - @qml.qnode(qml.device(backend, wires=3, shots=10000)) + @qml.qnode(dev) def circuit(x, y): qml.RX(x, wires=0) qml.RX(y, wires=1) @@ -344,13 +347,12 @@ def circuit(x, y): A = np.array( [[complex(1.0, 0.0), complex(2.0, 0.0)], [complex(2.0, 0.0), complex(1.0, 0.0)]] ) - return qml.var(qml.Hermitian(A, wires=2) + qml.PauliX(0) + qml.Hermitian(A, wires=1)) + return qml.var(qml.Hermitian(A, wires=2)) - with pytest.raises( - RuntimeError, - match="Hermitian observables with shot measurement are not supported", - ): - circuit(np.pi / 4, np.pi / 4) + expected = circuit(np.pi / 4, np.pi / 4) + result = qjit(circuit)(np.pi / 4, np.pi / 4) + + assert np.allclose(result, expected, atol=tol_stochastic, rtol=tol_stochastic) def test_paulix_pauliy(self, backend, tol_stochastic): """Test that a tensor product involving PauliX and PauliY works correctly""" @@ -480,6 +482,24 @@ def circuit(theta): result = qjit(circuit)(0.432) assert np.allclose(result, expected, atol=tol_stochastic, rtol=tol_stochastic) + # TODO: Support probs with observables + def test_probs_obs(self, backend): + """Test probs with an observable""" + + n_wires = 1 + n_shots = 10000 + dev = qml.device(backend, wires=n_wires, shots=n_shots) + + matrix = 1 / np.sqrt(2) * np.array([[1, 1], [1, -1]]) + + @qml.qnode(dev) + def circuit(theta): + qml.RX(theta, wires=[0]) + return qml.probs(op=qml.Hermitian(matrix, wires=0)) + + with pytest.raises(AssertionError): + qjit(circuit)(0.432) + class TestShadow: """Test shadow.""" diff --git a/runtime/README.rst b/runtime/README.rst index 0770c068ec..8a881e5a2a 100644 --- a/runtime/README.rst +++ b/runtime/README.rst @@ -63,16 +63,16 @@ The following table shows the available devices along with supported features: - ``Identity``, ``PauliX``, ``PauliY``, ``PauliZ``, ``Hadamard``, ``Hermitian``, ``Hamiltonian``, and Tensor Product of Observables - ``Identity``, ``PauliX``, ``PauliY``, ``PauliZ``, ``Hadamard``, ``Hermitian``, and Tensor Product of Observables * - Expectation Value - - All observables; Finite-shots supported except for ``Hermitian`` - - All observables; Finite-shots supported except for ``Hermitian`` + - All observables; Finite-shots supported + - All observables; Finite-shots supported - All observables; Finite-shots supported * - Variance - - All observables; Finite-shots supported except for ``Hermitian`` - - All observables; Finite-shots supported except for ``Hermitian`` + - All observables; Finite-shots supported + - All observables; Finite-shots supported - All observables; Finite-shots supported * - Probability - - Only for the computational basis on the supplied qubits; Finite-shots supported except for ``Hermitian`` - - Only for the computational basis on the supplied qubits; Finite-shots supported except for ``Hermitian`` + - Only for the computational basis on the supplied qubits; Finite-shots supported + - Only for the computational basis on the supplied qubits; Finite-shots supported - The computational basis on all active qubits; Finite-shots supported * - Sampling - Only for the computational basis on the supplied qubits