From 2cd824751215b28fdb7b176bac3447bb4e4d5727 Mon Sep 17 00:00:00 2001 From: Shuli Shu <31480676+multiphaseCFD@users.noreply.github.com> Date: Wed, 23 Aug 2023 08:59:37 -0400 Subject: [PATCH] Rename qubitstatevector to stateprep (#134) * rename qubitstatevector to stateprep * default.qubit as bench * Trigger multi-GPU CI * add changelog * update pybind to 2.11.1 (test) * Fix typo in changelog. * Revert pybind11 version to match lightning. Fix couple imports. Add formatting tools to reqs. * Deprecate python 3.8. * Build pennylane-lightning@update/nested_cmake_paths * Build against update/nested_cmake_paths * Revert to building against PLL@master * WIP * Change template input of templated OpsData. * replace StateVectorRawCPU.hpp StateVectorLQubitRaw.hpp * Increase CUDA ver to 20. * Fix cpp tests headers and linking. * Update pennylane ver in docs. * Update cuda ver 12. * Install devtoolset-11 * Uninstall devtoolset-10 * Build against PLL bugfix/numbers. * Build against pennylane-lightning.git@bugfix/numbers * pull pennylane-lightning.git@bugfix/numbers * Reintroduce QubitStateVector. * Reformat & fix pytest.raise. * Remove python 3.8 refs. * Change Lightning build branch from bugfix/numbers to master. * Update CHANGELOG.md * Update devices.rst * Fix custatevec ver in reqs. * Parametrize couple parallel tests over stateprep. --------- Co-authored-by: Vincent Michaud-Rioux --- .github/CHANGELOG.md | 11 ++- .../workflows/build_wheel_manylinux2014.yml | 6 +- .github/workflows/format.yml | 2 +- .github/workflows/tests_linux_x86.yml | 6 +- .github/workflows/tests_linux_x86_mpich.yml | 6 +- .github/workflows/tests_linux_x86_openmpi.yml | 6 +- CMakeLists.txt | 14 ++-- Makefile | 8 +-- README.rst | 4 +- doc/devices.rst | 3 +- doc/requirements.txt | 2 +- mpitests/test_adjoint_jacobian.py | 12 ++-- mpitests/test_apply.py | 18 ++--- pennylane_lightning_gpu/_serialize.py | 4 +- pennylane_lightning_gpu/lightning_gpu.py | 11 +-- .../src/algorithms/AdjointDiffGPU.hpp | 55 ++++++++------- .../src/algorithms/AdjointDiffGPUMPI.hpp | 34 +++++---- .../src/algorithms/CMakeLists.txt | 2 +- .../src/bindings/Bindings.cpp | 66 +++++++++-------- .../src/simulator/CMakeLists.txt | 2 +- .../src/simulator/StateVectorCudaBase.hpp | 7 +- .../src/simulator/StateVectorCudaMPI.hpp | 2 +- .../src/simulator/StateVectorCudaManaged.hpp | 2 + .../src/tests/CMakeLists.txt | 28 ++++---- .../{TestHelpers.hpp => TestHelpersLGPU.hpp} | 4 +- .../src/tests/Test_AdjointDiffGPU.cpp | 30 ++++---- .../src/tests/Test_DataBuffer.cpp | 2 +- .../src/tests/Test_GateCache.cpp | 2 +- .../src/tests/Test_Generators.cpp | 2 +- .../src/tests/Test_ObservablesGPU.cpp | 2 +- .../Test_StateVectorCudaManaged_NonParam.cpp | 4 +- .../Test_StateVectorCudaManaged_Param.cpp | 24 ++++--- .../src/tests/mpi/Test_MPIManager.cpp | 2 +- .../src/tests/mpi/Test_MPI_AdjointDiffGPU.cpp | 2 +- .../mpi/Test_StateVectorCudaMPI_NonParam.cpp | 4 +- .../mpi/Test_StateVectorCudaMPI_Param.cpp | 4 +- requirements.txt | 4 +- setup.py | 1 - tests/test_adjoint_jacobian.py | 14 ++-- tests/test_apply.py | 70 ++++++++++--------- tests/test_comparison.py | 57 +++++++-------- tests/test_gates.py | 4 +- 42 files changed, 299 insertions(+), 244 deletions(-) rename pennylane_lightning_gpu/src/tests/{TestHelpers.hpp => TestHelpersLGPU.hpp} (98%) diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index 846cb74b..a98f9282 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -7,6 +7,15 @@ ### Breaking changes + * Rename `QubitStateVector` to `StatePrep` in the `LightningGPU` class. + [#134] (https://github.com/PennyLaneAI/pennylane-lightning-gpu/pull/134) + + * Deprecate Python 3.8. + [#134] (https://github.com/PennyLaneAI/pennylane-lightning-gpu/pull/134) + + * Update PennyLane-Lightning imports following the [(#472)] (https://github.com/PennyLaneAI/pennylane-lightning/pull/472) refactoring. + [#134] (https://github.com/PennyLaneAI/pennylane-lightning-gpu/pull/134) + ### Improvements * Optimizes the single qubit rotation gate by using a single cuStateVector API call instead of separate Pauli gate applications. @@ -23,7 +32,7 @@ This release contains contributions from (in alphabetical order): -David Clark (NVIDIA), Shuli Shu +David Clark (NVIDIA), Vincent Michaud-Rioux, Shuli Shu --- diff --git a/.github/workflows/build_wheel_manylinux2014.yml b/.github/workflows/build_wheel_manylinux2014.yml index 3e71b409..51384e0a 100644 --- a/.github/workflows/build_wheel_manylinux2014.yml +++ b/.github/workflows/build_wheel_manylinux2014.yml @@ -1,7 +1,7 @@ name: Wheel::Linux::x86_64 # **What it does**: Builds python wheels for Linux (ubuntu-latest) architecture x86_64 and store it as artifacts. -# Python versions: 3.8, 3.9, 3.10, 3.11. +# Python versions: 3.9, 3.10, 3.11. # **Why we have it**: To build wheels for pennylane-lightning-gpu installation. # **Who does it impact**: Wheels to be uploaded to PyPI. @@ -27,7 +27,7 @@ jobs: os: [ubuntu-latest] arch: [x86_64] cibw_build: ${{ fromJson(needs.set_wheel_build_matrix.outputs.python_version) }} - name: ${{ matrix.os }} (Python ${{ fromJson('{"cp38-*":"3.8","cp39-*":"3.9","cp310-*":"3.10","cp311-*":"3.11" }')[matrix.cibw_build] }}) + name: ${{ matrix.os }} (Python ${{ fromJson('{ "cp39-*":"3.9","cp310-*":"3.10","cp311-*":"3.11" }')[matrix.cibw_build] }}) runs-on: ${{ matrix.os }} steps: @@ -42,7 +42,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v4 with: - python-version: '3.8' + python-version: '3.9' - name: Install cibuildwheel run: python -m pip install cibuildwheel~=2.11.0 diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index d4d21f29..17b42c50 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -17,7 +17,7 @@ jobs: - uses: actions/setup-python@v4 name: Install Python with: - python-version: '3.8' + python-version: '3.9' - name: Install dependencies run: diff --git a/.github/workflows/tests_linux_x86.yml b/.github/workflows/tests_linux_x86.yml index 36674a51..7acc3737 100644 --- a/.github/workflows/tests_linux_x86.yml +++ b/.github/workflows/tests_linux_x86.yml @@ -69,7 +69,7 @@ jobs: id: setup_python name: Install Python with: - python-version: '3.8' + python-version: '3.9' # Since the self-hosted runner can be re-used. It is best to set up all package # installations in a virtual environment that gets cleaned at the end of each workflow run @@ -215,7 +215,7 @@ jobs: id: setup_python name: Install Python with: - python-version: '3.8' + python-version: '3.9' # Since the self-hosted runner can be re-used. It is best to set up all package # installations in a virtual environment that gets cleaned at the end of each workflow run @@ -259,7 +259,7 @@ jobs: python -m pip install pip~=22.0 python -m pip install ninja cmake custatevec-cu11 pytest pytest-mock flaky pytest-cov # Sync with latest master branches - python -m pip install --index-url https://test.pypi.org/simple/ pennylane-lightning --pre --force-reinstall --no-deps + python -m pip install git+https://github.com/PennyLaneAI/pennylane-lightning.git@master --force-reinstall --no-deps - name: Build and install package env: diff --git a/.github/workflows/tests_linux_x86_mpich.yml b/.github/workflows/tests_linux_x86_mpich.yml index bd77c326..2e517ef8 100644 --- a/.github/workflows/tests_linux_x86_mpich.yml +++ b/.github/workflows/tests_linux_x86_mpich.yml @@ -55,7 +55,7 @@ jobs: id: setup_python name: Install Python with: - python-version: '3.8' + python-version: '3.9' # Since the self-hosted runner can be re-used. It is best to set up all package # installations in a virtual environment that gets cleaned at the end of each workflow run @@ -225,7 +225,7 @@ jobs: id: setup_python name: Install Python with: - python-version: '3.8' + python-version: '3.9' # Since the self-hosted runner can be re-used. It is best to set up all package # installations in a virtual environment that gets cleaned at the end of each workflow run @@ -275,7 +275,7 @@ jobs: python -m pip install pip~=22.0 python -m pip install ninja cmake custatevec-cu11 pytest pytest-mock flaky pytest-cov mpi4py # Sync with latest master branches - python -m pip install --index-url https://test.pypi.org/simple/ pennylane-lightning --pre --force-reinstall --no-deps + python -m pip install git+https://github.com/PennyLaneAI/pennylane-lightning.git@master --force-reinstall --no-deps - name: Build and install package (MPICH backend) env: diff --git a/.github/workflows/tests_linux_x86_openmpi.yml b/.github/workflows/tests_linux_x86_openmpi.yml index 941ed3ee..fca6693d 100644 --- a/.github/workflows/tests_linux_x86_openmpi.yml +++ b/.github/workflows/tests_linux_x86_openmpi.yml @@ -38,7 +38,7 @@ jobs: id: setup_python name: Install Python with: - python-version: '3.8' + python-version: '3.9' # Since the self-hosted runner can be re-used. It is best to set up all package # installations in a virtual environment that gets cleaned at the end of each workflow run @@ -197,7 +197,7 @@ jobs: id: setup_python name: Install Python with: - python-version: '3.8' + python-version: '3.9' # Since the self-hosted runner can be re-used. It is best to set up all package # installations in a virtual environment that gets cleaned at the end of each workflow run @@ -247,7 +247,7 @@ jobs: python -m pip install pip~=22.0 python -m pip install ninja cmake custatevec-cu11 pytest pytest-mock flaky pytest-cov mpi4py # Sync with latest master branches - python -m pip install --index-url https://test.pypi.org/simple/ pennylane-lightning --pre --force-reinstall --no-deps + python -m pip install git+https://github.com/PennyLaneAI/pennylane-lightning.git@master --force-reinstall --no-deps - name: Build and install package (OpenMPI backend) env: diff --git a/CMakeLists.txt b/CMakeLists.txt index a2bd7e95..ead1769e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -109,7 +109,7 @@ set(ENABLE_KOKKOS OFF) FetchContent_Declare( pennylane_lightning GIT_REPOSITORY https://github.com/PennyLaneAI/pennylane-lightning.git - GIT_TAG "${LIGHTNING_RELEASE_TAG}" + GIT_TAG master ) FetchContent_MakeAvailable(pennylane_lightning) @@ -200,12 +200,12 @@ endif() # Create binding module if(PLLGPU_ENABLE_PYTHON) - pybind11_add_module(lightning_gpu_qubit_ops "pennylane_lightning_gpu/src/bindings/Bindings.cpp") - target_link_libraries(lightning_gpu_qubit_ops PRIVATE pennylane_lightning_gpu) - set_target_properties(lightning_gpu_qubit_ops PROPERTIES CXX_VISIBILITY_PRESET hidden) - set_target_properties(lightning_gpu_qubit_ops PROPERTIES INSTALL_RPATH "$ORIGIN/../cuquantum/lib:$ORIGIN/../cuquantum/lib64:$ORIGIN/") - target_compile_options(lightning_gpu_qubit_ops PRIVATE "$<$:-W>") - target_compile_definitions(lightning_gpu_qubit_ops PRIVATE VERSION_INFO=${VERSION_STRING}) + pybind11_add_module(lightning_gpu_qubit_ops "pennylane_lightning_gpu/src/bindings/Bindings.cpp") + target_link_libraries(lightning_gpu_qubit_ops PRIVATE lightning_algorithms lightning_qubit lightning_qubit_algorithms pennylane_lightning_gpu) + set_target_properties(lightning_gpu_qubit_ops PROPERTIES CXX_VISIBILITY_PRESET hidden) + set_target_properties(lightning_gpu_qubit_ops PROPERTIES INSTALL_RPATH "$ORIGIN/../cuquantum/lib:$ORIGIN/../cuquantum/lib64:$ORIGIN/") + target_compile_options(lightning_gpu_qubit_ops PRIVATE "$<$:-W>") + target_compile_definitions(lightning_gpu_qubit_ops PRIVATE VERSION_INFO=${VERSION_STRING}) if(PLLGPU_ENABLE_MPI) option(ENABLE_MPI "Enable MPI support" ON) target_compile_definitions(lightning_gpu_qubit_ops PRIVATE ENABLE_MPI) diff --git a/Makefile b/Makefile index 84b6ef84..3d8eff44 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,7 @@ ifndef CUQUANTUM_SDK @test $(CUQUANTUM_SDK) endif ifndef PYTHON3 - @echo "To install PennyLane-Lightning-GPU you must have Python 3.8+ installed." + @echo "To install PennyLane-Lightning-GPU you must have Python 3.9+ installed." endif $(PYTHON) setup.py build_ext --cuquantum=$(CUQUANTUM_SDK) --verbose $(PYTHON) setup.py install @@ -85,13 +85,13 @@ ifndef CUQUANTUM_SDK @test $(CUQUANTUM_SDK) endif rm -rf ./BuildTests - cmake . -BBuildTests -DBUILD_TESTS=1 -DPLLGPU_BUILD_TESTS=1 -DCUQUANTUM_SDK=$(CUQUANTUM_SDK) + cmake . -BBuildTests -G Ninja -DBUILD_TESTS=1 -DPLLGPU_BUILD_TESTS=1 -DCUQUANTUM_SDK=$(CUQUANTUM_SDK) cmake --build ./BuildTests ./BuildTests/pennylane_lightning_gpu/src/tests/runner_gpu test-cpp-mpi: rm -rf ./BuildTests - cmake . -BBuildTests -DBUILD_TESTS=1 -DPLLGPU_BUILD_TESTS=1 -DPLLGPU_ENABLE_MPI=On -DCUQUANTUM_SDK=$(CUQUANTUM_SDK) + cmake . -BBuildTests -G Ninja -DBUILD_TESTS=1 -DPLLGPU_BUILD_TESTS=1 -DPLLGPU_ENABLE_MPI=On -DCUQUANTUM_SDK=$(CUQUANTUM_SDK) cmake --build ./BuildTests $(MPILAUNCHER) -np $(NUMPROCS) ./BuildTests/pennylane_lightning_gpu/src/tests/mpi_runner @@ -121,5 +121,5 @@ endif .PHONY: check-tidy check-tidy: rm -rf ./Build - cmake . -BBuild -DENABLE_CLANG_TIDY=ON -DBUILD_TESTS=1 + cmake . -BBuild -G Ninja -DENABLE_CLANG_TIDY=ON -DBUILD_TESTS=1 cmake --build ./Build diff --git a/README.rst b/README.rst index de2c8e04..76cc8677 100644 --- a/README.rst +++ b/README.rst @@ -37,7 +37,7 @@ Features Installation ============ -PennyLane-Lightning-GPU requires Python version 3.8 and above. It can be installed using ``pip``: +PennyLane-Lightning-GPU requires Python version 3.9 and above. It can be installed using ``pip``: .. code-block:: console @@ -82,7 +82,7 @@ To build using Docker, run the following from the project root directory: docker build . -f ./docker/Dockerfile -t "lightning-gpu-wheels" -This will build a Python wheel for Python 3.8 up to 3.11 inclusive, and be manylinux2014 (glibc 2.17) compatible. +This will build a Python wheel for Python 3.9 up to 3.11 inclusive, and be manylinux2014 (glibc 2.17) compatible. To acquire the built wheels, use: .. code-block:: console diff --git a/doc/devices.rst b/doc/devices.rst index 533ddd3e..f2b282ba 100644 --- a/doc/devices.rst +++ b/doc/devices.rst @@ -47,6 +47,7 @@ Supported operations and observables ~pennylane.PhaseShift ~pennylane.ControlledPhaseShift ~pennylane.QubitStateVector + ~pennylane.StatePrep ~pennylane.Rot ~pennylane.RX ~pennylane.RY @@ -241,4 +242,4 @@ To enable the memory-optimized adjoint method with MPI support, ``batch_obs`` sh dev = qml.device('lightning.gpu', wires= n_wires, mpi=True, batch_obs=True) -For the adjoint method, each MPI process will provide the overall simulation results. \ No newline at end of file +For the adjoint method, each MPI process will provide the overall simulation results. diff --git a/doc/requirements.txt b/doc/requirements.txt index d62a8c69..b1740347 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -6,5 +6,5 @@ exhale pybind11 cmake ninja -pennylane +git+https://github.com/PennyLaneAI/pennylane.git@master pennylane-sphinx-theme diff --git a/mpitests/test_adjoint_jacobian.py b/mpitests/test_adjoint_jacobian.py index b42f9e71..738ab4cd 100644 --- a/mpitests/test_adjoint_jacobian.py +++ b/mpitests/test_adjoint_jacobian.py @@ -174,7 +174,8 @@ def test_unsupported_hermitian_expectation(self, isBatch_obs): @pytest.mark.parametrize("theta", np.linspace(-2 * np.pi, 2 * np.pi, 7)) @pytest.mark.parametrize("G", [qml.RX, qml.RY, qml.RZ]) @pytest.mark.parametrize("isBatch_obs", [False, True]) - def test_pauli_rotation_gradient(self, G, theta, tol, isBatch_obs, request): + @pytest.mark.parametrize("stateprep", [qml.QubitStateVector, qml.StatePrep]) + def test_pauli_rotation_gradient(self, stateprep, G, theta, tol, isBatch_obs, request): """Tests that the automatic gradients of Pauli rotations are correct.""" num_wires = 3 @@ -188,7 +189,7 @@ def test_pauli_rotation_gradient(self, G, theta, tol, isBatch_obs, request): dev_cpu = qml.device("default.qubit", wires=3) with qml.tape.QuantumTape() as tape: - qml.QubitStateVector(np.array([1.0, -1.0]) / np.sqrt(2), wires=0) + stateprep(np.array([1.0, -1.0]) / np.sqrt(2), wires=0) G(theta, wires=[0]) qml.expval(qml.PauliZ(0)) @@ -202,7 +203,8 @@ def test_pauli_rotation_gradient(self, G, theta, tol, isBatch_obs, request): @pytest.fixture(params=[np.complex64, np.complex128]) @pytest.mark.parametrize("theta", np.linspace(-2 * np.pi, 2 * np.pi, 7)) @pytest.mark.parametrize("isBatch_obs", [False, True]) - def test_Rot_gradient(self, theta, tol, isBatch_obs, request): + @pytest.mark.parametrize("stateprep", [qml.QubitStateVector, qml.StatePrep]) + def test_Rot_gradient(self, stateprep, theta, tol, isBatch_obs, request): """Tests that the device gradient of an arbitrary Euler-angle-parameterized gate is correct.""" num_wires = 3 @@ -218,7 +220,7 @@ def test_Rot_gradient(self, theta, tol, isBatch_obs, request): params = np.array([theta, theta**3, np.sqrt(2) * theta]) with qml.tape.QuantumTape() as tape: - qml.QubitStateVector(np.array([1.0, -1.0]) / np.sqrt(2), wires=0) + stateprep(np.array([1.0, -1.0]) / np.sqrt(2), wires=0) qml.Rot(*params, wires=[0]) qml.expval(qml.PauliZ(0)) @@ -760,7 +762,7 @@ def circuit_2(params, wires): def circuit_ansatz(params, wires): """Circuit ansatz containing all the parametrized gates""" - qml.QubitStateVector(unitary_group.rvs(2**6, random_state=0)[0], wires=wires) + qml.StatePrep(unitary_group.rvs(2**6, random_state=0)[0], wires=wires) qml.RX(params[0], wires=wires[0]) qml.RY(params[1], wires=wires[1]) qml.adjoint(qml.RX(params[2], wires=wires[2])) diff --git a/mpitests/test_apply.py b/mpitests/test_apply.py index 211469b1..146081a5 100644 --- a/mpitests/test_apply.py +++ b/mpitests/test_apply.py @@ -72,7 +72,7 @@ def apply_operation_gates_qnode_param(tol, operation, par, Wires): ) def circuit(*params): - qml.QubitStateVector(state_vector, wires=range(num_wires)) + qml.StatePrep(state_vector, wires=range(num_wires)) operation(*params, wires=Wires) return qml.state() @@ -105,7 +105,7 @@ def apply_operation_gates_apply_param(tol, operation, par, Wires): @qml.qnode(dev_cpu) def circuit(*params): - qml.QubitStateVector(state_vector, wires=range(num_wires)) + qml.StatePrep(state_vector, wires=range(num_wires)) operation(*params, wires=Wires) return qml.state() @@ -153,7 +153,7 @@ def apply_operation_gates_qnode_nonparam(tol, operation, Wires): ) def circuit(): - qml.QubitStateVector(state_vector, wires=range(num_wires)) + qml.StatePrep(state_vector, wires=range(num_wires)) operation(wires=Wires) return qml.state() @@ -186,7 +186,7 @@ def apply_operation_gates_apply_nonparam(tol, operation, Wires): @qml.qnode(dev_cpu) def circuit(): - qml.QubitStateVector(state_vector, wires=range(num_wires)) + qml.StatePrep(state_vector, wires=range(num_wires)) operation(wires=Wires) return qml.state() @@ -225,7 +225,7 @@ def expval_single_wire_no_param(tol, obs): dev_gpumpi = qml.device("lightning.gpu", wires=num_wires, mpi=True, c_dtype=np.complex128) def circuit(): - qml.QubitStateVector(state_vector, wires=range(num_wires)) + qml.StatePrep(state_vector, wires=range(num_wires)) return qml.expval(obs) cpu_qnode = qml.QNode(circuit, dev_cpu) @@ -252,7 +252,7 @@ def apply_probs_nonparam(tol, operation, GateWires, Wires): dev_gpumpi = qml.device("lightning.gpu", wires=num_wires, mpi=True, c_dtype=np.complex128) def circuit(): - qml.QubitStateVector(state_vector, wires=range(num_wires)) + qml.StatePrep(state_vector, wires=range(num_wires)) operation(wires=GateWires) return qml.probs(wires=Wires) @@ -292,7 +292,7 @@ def apply_probs_param(tol, operation, par, GateWires, Wires): dev_gpumpi = qml.device("lightning.gpu", wires=num_wires, mpi=True, c_dtype=np.complex128) def circuit(): - qml.QubitStateVector(state_vector, wires=range(num_wires)) + qml.StatePrep(state_vector, wires=range(num_wires)) operation(*par, wires=GateWires) return qml.probs(wires=Wires) @@ -501,7 +501,7 @@ def test_qubit_state_prep(self, tol, par, Wires): dev_gpumpi = qml.device("lightning.gpu", wires=num_wires, mpi=True, c_dtype=np.complex128) def circuit(): - qml.QubitStateVector(par, wires=Wires) + qml.StatePrep(par, wires=Wires) return qml.state() cpu_qnode = qml.QNode(circuit, dev_cpu) @@ -1152,7 +1152,7 @@ def test_prob_four_wire_param(self, tol, operation, par, GateWires, Wires): def circuit_ansatz(params, wires): """Circuit ansatz containing all the parametrized gates""" - qml.QubitStateVector(unitary_group.rvs(2**numQubits, random_state=0)[0], wires=wires) + qml.StatePrep(unitary_group.rvs(2**numQubits, random_state=0)[0], wires=wires) qml.RX(params[0], wires=wires[0]) qml.RY(params[1], wires=wires[1]) qml.adjoint(qml.RX(params[2], wires=wires[2])) diff --git a/pennylane_lightning_gpu/_serialize.py b/pennylane_lightning_gpu/_serialize.py index e989ed49..f6e630d4 100644 --- a/pennylane_lightning_gpu/_serialize.py +++ b/pennylane_lightning_gpu/_serialize.py @@ -24,7 +24,7 @@ PauliY, PauliZ, Identity, - QubitStateVector, + StatePrep, Rot, ) from pennylane.operation import Tensor @@ -286,7 +286,7 @@ def _serialize_ops( sv_py = LightningGPU_C64 if use_csingle else LightningGPU_C128 for o in tape.operations: - if isinstance(o, (BasisState, QubitStateVector)): + if isinstance(o, (BasisState, StatePrep)): uses_stateprep = True continue elif isinstance(o, Rot): diff --git a/pennylane_lightning_gpu/lightning_gpu.py b/pennylane_lightning_gpu/lightning_gpu.py index 2c88ea67..4c181007 100644 --- a/pennylane_lightning_gpu/lightning_gpu.py +++ b/pennylane_lightning_gpu/lightning_gpu.py @@ -27,14 +27,14 @@ math, QubitDevice, BasisState, - QubitStateVector, + StatePrep, DeviceError, Projector, Hermitian, Rot, QuantumFunctionError, ) -from pennylane_lightning import LightningQubit +from pennylane_lightning.lightning_qubit import LightningQubit from pennylane.operation import Tensor, Operation from pennylane.ops.op_math import Adjoint from pennylane.measurements import Expectation, MeasurementProcess, State @@ -142,6 +142,7 @@ def _mebibytesToBytes(mebibytes): "Identity", "BasisState", "QubitStateVector", + "StatePrep", "QubitUnitary", "ControlledQubitUnitary", "MultiControlledX", @@ -554,7 +555,7 @@ def apply_cq(self, operations, **kwargs): def apply(self, operations, **kwargs): # State preparation is currently done in Python if operations: # make sure operations[0] exists - if isinstance(operations[0], QubitStateVector): + if isinstance(operations[0], StatePrep): self._apply_state_vector_GPU( operations[0].parameters[0].copy(), operations[0].wires ) @@ -564,7 +565,7 @@ def apply(self, operations, **kwargs): operations = operations[1:] for operation in operations: - if isinstance(operation, (QubitStateVector, BasisState)): + if isinstance(operation, (StatePrep, BasisState)): raise DeviceError( "Operation {} cannot be used after other Operations have already been " "applied on a {} device.".format(operation.name, self.short_name) @@ -678,7 +679,7 @@ def adjoint_jacobian(self, tape, starting_state=None, use_device_state=False, ** # get op_idx-th operator among differentiable operators op, _, _ = tape.get_operation(op_idx) - if isinstance(op, Operation) and not isinstance(op, (BasisState, QubitStateVector)): + if isinstance(op, Operation) and not isinstance(op, (BasisState, StatePrep)): # We now just ignore non-op or state preps tp_shift.append(tp) record_tp_rows.append(all_params) diff --git a/pennylane_lightning_gpu/src/algorithms/AdjointDiffGPU.hpp b/pennylane_lightning_gpu/src/algorithms/AdjointDiffGPU.hpp index f1502c27..415d9fcb 100644 --- a/pennylane_lightning_gpu/src/algorithms/AdjointDiffGPU.hpp +++ b/pennylane_lightning_gpu/src/algorithms/AdjointDiffGPU.hpp @@ -26,7 +26,7 @@ #include "DevTag.hpp" #include "DevicePool.hpp" #include "GateGenerators.hpp" -#include "JacobianTape.hpp" +#include "JacobianData.hpp" #include "ObservablesGPU.hpp" #include "StateVectorCudaManaged.hpp" @@ -163,17 +163,18 @@ template class AdjointJacobianGPU { /** * @brief Utility method to apply all operations from given - * `%Pennylane::Algorithms::OpsData` object to + * `%Pennylane::Algorithms::OpsData>` object to * `%StateVectorCudaManaged` * * @param state Statevector to be updated. * @param operations Operations to apply. * @param adj Take the adjoint of the given operations. */ - inline void - applyOperations(StateVectorCudaManaged &state, - const Pennylane::Algorithms::OpsData &operations, - bool adj = false) { + inline void applyOperations( + StateVectorCudaManaged &state, + const Pennylane::Algorithms::OpsData> + &operations, + bool adj = false) { for (size_t op_idx = 0; op_idx < operations.getOpsName().size(); op_idx++) { state.applyOperation(operations.getOpsName()[op_idx], @@ -185,17 +186,18 @@ template class AdjointJacobianGPU { /** * @brief Utility method to apply the adjoint indexed operation from - * `%Pennylane::Algorithms::OpsData` object to + * `%Pennylane::Algorithms::OpsData>` object to * `%StateVectorCudaManaged`. * * @param state Statevector to be updated. * @param operations Operations to apply. * @param op_idx Adjointed operation index to apply. */ - inline void - applyOperationAdj(StateVectorCudaManaged &state, - const Pennylane::Algorithms::OpsData &operations, - size_t op_idx) { + inline void applyOperationAdj( + StateVectorCudaManaged &state, + const Pennylane::Algorithms::OpsData> + &operations, + size_t op_idx) { state.applyOperation(operations.getOpsName()[op_idx], operations.getOpsWires()[op_idx], !operations.getOpsInverses()[op_idx], @@ -274,10 +276,11 @@ template class AdjointJacobianGPU { * @param op_idx Index of given operation within operations list to take * adjoint of. */ - inline void - applyOperationsAdj(std::vector> &states, - const Pennylane::Algorithms::OpsData &operations, - size_t op_idx) { + inline void applyOperationsAdj( + std::vector> &states, + const Pennylane::Algorithms::OpsData> + &operations, + size_t op_idx) { // clang-format off // Globally scoped exception value to be captured within OpenMP block. // See the following for OpenMP design decisions: @@ -358,7 +361,7 @@ template class AdjointJacobianGPU { * @param ops_inverses Indicate whether to take adjoint of each operation in * ops_name. * @param ops_matrices Matrix definition of an operation if unsupported. - * @return const Pennylane::Algorithms::OpsData + * @return const Pennylane::Algorithms::OpsData> */ auto createOpsData( const std::vector &ops_name, @@ -366,7 +369,7 @@ template class AdjointJacobianGPU { const std::vector> &ops_wires, const std::vector &ops_inverses, const std::vector>> &ops_matrices = {{}}) - -> Pennylane::Algorithms::OpsData { + -> Pennylane::Algorithms::OpsData> { return {ops_name, ops_params, ops_wires, ops_inverses, ops_matrices}; } @@ -390,7 +393,7 @@ template class AdjointJacobianGPU { const CFP_t *ref_data, std::size_t length, std::vector> &jac, const std::vector>> &obs, - const Pennylane::Algorithms::OpsData &ops, + const Pennylane::Algorithms::OpsData> &ops, const std::vector &trainableParams, bool apply_operations = false) { @@ -493,14 +496,13 @@ template class AdjointJacobianGPU { * @param apply_operations Indicate whether to apply operations to psi prior * to calculation. */ - void - adjointJacobian(const CFP_t *ref_data, std::size_t length, - std::vector> &jac, - const std::vector>> &obs, - const Pennylane::Algorithms::OpsData &ops, - const std::vector &trainableParams, - bool apply_operations = false, - CUDA::DevTag dev_tag = {0, 0}) { + void adjointJacobian( + const CFP_t *ref_data, std::size_t length, + std::vector> &jac, + const std::vector>> &obs, + const Pennylane::Algorithms::OpsData> &ops, + const std::vector &trainableParams, + bool apply_operations = false, CUDA::DevTag dev_tag = {0, 0}) { PL_ABORT_IF(trainableParams.empty(), "No trainable parameters provided."); @@ -561,6 +563,7 @@ template class AdjointJacobianGPU { "The operation is not supported using the adjoint " "differentiation method"); if ((ops_name[op_idx] == "QubitStateVector") || + (ops_name[op_idx] == "StatePrep") || (ops_name[op_idx] == "BasisState")) { continue; } diff --git a/pennylane_lightning_gpu/src/algorithms/AdjointDiffGPUMPI.hpp b/pennylane_lightning_gpu/src/algorithms/AdjointDiffGPUMPI.hpp index 0e3ec4b1..194a21fb 100644 --- a/pennylane_lightning_gpu/src/algorithms/AdjointDiffGPUMPI.hpp +++ b/pennylane_lightning_gpu/src/algorithms/AdjointDiffGPUMPI.hpp @@ -19,7 +19,7 @@ #include "DevTag.hpp" #include "GateGenerators.hpp" -#include "JacobianTape.hpp" +#include "JacobianData.hpp" #include "ObservablesGPUMPI.hpp" #include "StateVectorCudaMPI.hpp" #include @@ -131,17 +131,18 @@ class AdjointJacobianGPUMPI { /** * @brief Utility method to apply all operations from given - * `%Pennylane::Algorithms::OpsData` object to + * `%Pennylane::Algorithms::OpsData>` object to * `%SVType` * * @param state Statevector to be updated. * @param operations Operations to apply. * @param adj Take the adjoint of the given operations. */ - inline void - applyOperations(SVType &state, - const Pennylane::Algorithms::OpsData &operations, - bool adj = false) { + inline void applyOperations( + SVType &state, + const Pennylane::Algorithms::OpsData> + &operations, + bool adj = false) { for (size_t op_idx = 0; op_idx < operations.getOpsName().size(); op_idx++) { state.applyOperation(operations.getOpsName()[op_idx], @@ -153,17 +154,18 @@ class AdjointJacobianGPUMPI { /** * @brief Utility method to apply the adjoint indexed operation from - * `%Pennylane::Algorithms::OpsData` object to + * `%Pennylane::Algorithms::OpsData>` object to * `%SVType`. * * @param state Statevector to be updated. * @param operations Operations to apply. * @param op_idx Adjointed operation index to apply. */ - inline void - applyOperationAdj(SVType &state, - const Pennylane::Algorithms::OpsData &operations, - size_t op_idx) { + inline void applyOperationAdj( + SVType &state, + const Pennylane::Algorithms::OpsData> + &operations, + size_t op_idx) { state.applyOperation(operations.getOpsName()[op_idx], operations.getOpsWires()[op_idx], !operations.getOpsInverses()[op_idx], @@ -212,7 +214,7 @@ class AdjointJacobianGPUMPI { * @param ops_inverses Indicate whether to take adjoint of each operation in * ops_name. * @param ops_matrices Matrix definition of an operation if unsupported. - * @return const Pennylane::Algorithms::OpsData + * @return const Pennylane::Algorithms::OpsData> */ auto createOpsData( const std::vector &ops_name, @@ -220,7 +222,7 @@ class AdjointJacobianGPUMPI { const std::vector> &ops_wires, const std::vector &ops_inverses, const std::vector>> &ops_matrices = {{}}) - -> Pennylane::Algorithms::OpsData { + -> Pennylane::Algorithms::OpsData> { return {ops_name, ops_params, ops_wires, ops_inverses, ops_matrices}; } @@ -246,7 +248,7 @@ class AdjointJacobianGPUMPI { void adjointJacobian_serial( const SVType &ref_sv, std::vector> &jac, const std::vector>> &obs, - const Pennylane::Algorithms::OpsData &ops, + const Pennylane::Algorithms::OpsData> &ops, const std::vector &trainableParams, bool apply_operations = false) { PL_ABORT_IF(trainableParams.empty(), @@ -301,6 +303,7 @@ class AdjointJacobianGPUMPI { "The operation is not supported using the adjoint " "differentiation method"); if ((ops_name[op_idx] == "QubitStateVector") || + (ops_name[op_idx] == "StatePrep") || (ops_name[op_idx] == "BasisState")) { continue; } @@ -346,7 +349,7 @@ class AdjointJacobianGPUMPI { void adjointJacobian( const SVType &ref_sv, std::vector> &jac, const std::vector>> &obs, - const Pennylane::Algorithms::OpsData &ops, + const Pennylane::Algorithms::OpsData> &ops, const std::vector &trainableParams, bool apply_operations = false) { PL_ABORT_IF(trainableParams.empty(), @@ -397,6 +400,7 @@ class AdjointJacobianGPUMPI { "The operation is not supported using the adjoint " "differentiation method"); if ((ops_name[op_idx] == "QubitStateVector") || + (ops_name[op_idx] == "StatePrep") || (ops_name[op_idx] == "BasisState")) { continue; } diff --git a/pennylane_lightning_gpu/src/algorithms/CMakeLists.txt b/pennylane_lightning_gpu/src/algorithms/CMakeLists.txt index 90bcedc0..120edefe 100644 --- a/pennylane_lightning_gpu/src/algorithms/CMakeLists.txt +++ b/pennylane_lightning_gpu/src/algorithms/CMakeLists.txt @@ -10,5 +10,5 @@ endif() add_library(lightning_gpu_algorithms STATIC ${GPU_ALGORITHM_FILES}) target_include_directories(lightning_gpu_algorithms PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ) -target_link_libraries(lightning_gpu_algorithms PUBLIC pennylane_lightning lightning_gpu_simulator lightning_gpu_utils) +target_link_libraries(lightning_gpu_algorithms PUBLIC pennylane_lightning lightning_algorithms lightning_qubit lightning_gpu_simulator lightning_gpu_utils) set_property(TARGET lightning_gpu_algorithms PROPERTY POSITION_INDEPENDENT_CODE ON) \ No newline at end of file diff --git a/pennylane_lightning_gpu/src/bindings/Bindings.cpp b/pennylane_lightning_gpu/src/bindings/Bindings.cpp index 2b0d677d..83666372 100644 --- a/pennylane_lightning_gpu/src/bindings/Bindings.cpp +++ b/pennylane_lightning_gpu/src/bindings/Bindings.cpp @@ -19,16 +19,16 @@ #include "cuda.h" -#include "AdjointDiff.hpp" #include "AdjointDiffGPU.hpp" -#include "JacobianTape.hpp" +#include "AdjointJacobianLQubit.hpp" +#include "JacobianData.hpp" #include "DevTag.hpp" #include "DevicePool.hpp" #include "Error.hpp" #include "StateVectorCudaManaged.hpp" -#include "StateVectorManagedCPU.hpp" -#include "StateVectorRawCPU.hpp" +#include "StateVectorLQubitManaged.hpp" +#include "StateVectorLQubitRaw.hpp" #include "cuGateCache.hpp" #include "cuda_helpers.hpp" @@ -557,7 +557,7 @@ void StateVectorCudaManaged_class_bindings(py::module &m) { bool async) { sv.updateData(other, async); }, "Synchronize data from another GPU device to current device.") .def("DeviceToHost", - py::overload_cast &, bool>( + py::overload_cast &, bool>( &StateVectorCudaManaged::CopyGpuDataToHost, py::const_), "Synchronize data from the GPU device to host.") @@ -770,27 +770,29 @@ void StateVectorCudaManaged_class_bindings(py::module &m) { //***********************************************************************// class_name = "OpsStructGPU_C" + bitsize; - py::class_>(m, class_name.c_str(), py::module_local()) + py::class_>>( + m, class_name.c_str(), py::module_local()) .def(py::init< const std::vector &, const std::vector> &, const std::vector> &, const std::vector &, const std::vector>> &>()) - .def("__repr__", [](const OpsData &ops) { - using namespace Pennylane::Util; - std::ostringstream ops_stream; - for (size_t op = 0; op < ops.getSize(); op++) { - ops_stream << "{'name': " << ops.getOpsName()[op]; - ops_stream << ", 'params': " << ops.getOpsParams()[op]; - ops_stream << ", 'inv': " << ops.getOpsInverses()[op]; - ops_stream << "}"; - if (op < ops.getSize() - 1) { - ops_stream << ","; - } - } - return "Operations: [" + ops_stream.str() + "]"; - }); + .def("__repr__", + [](const OpsData> &ops) { + using namespace Pennylane::Util; + std::ostringstream ops_stream; + for (size_t op = 0; op < ops.getSize(); op++) { + ops_stream << "{'name': " << ops.getOpsName()[op]; + ops_stream << ", 'params': " << ops.getOpsParams()[op]; + ops_stream << ", 'inv': " << ops.getOpsInverses()[op]; + ops_stream << "}"; + if (op < ops.getSize() - 1) { + ops_stream << ","; + } + } + return "Operations: [" + ops_stream.str() + "]"; + }); //***********************************************************************// // Adj Jac @@ -831,8 +833,9 @@ void StateVectorCudaManaged_class_bindings(py::module &m) { } } - return OpsData{ops_name, conv_params, ops_wires, - ops_inverses, conv_matrices}; + return OpsData>{ + ops_name, conv_params, ops_wires, ops_inverses, + conv_matrices}; }) .def("adjoint_jacobian", &AdjointJacobianGPU::adjointJacobian) @@ -841,7 +844,8 @@ void StateVectorCudaManaged_class_bindings(py::module &m) { const StateVectorCudaManaged &sv, const std::vector>> &observables, - const Pennylane::Algorithms::OpsData &operations, + const Pennylane::Algorithms::OpsData< + StateVectorCudaManaged> &operations, const std::vector &trainableParams) { std::vector> jac( observables.size(), @@ -857,7 +861,8 @@ void StateVectorCudaManaged_class_bindings(py::module &m) { const StateVectorCudaManaged &sv, const std::vector>> &observables, - const Pennylane::Algorithms::OpsData &operations, + const Pennylane::Algorithms::OpsData< + StateVectorCudaManaged> &operations, const std::vector &trainableParams) { std::vector> jac( observables.size(), @@ -1421,7 +1426,7 @@ void StateVectorCudaMPI_class_bindings(py::module &m) { "Synchronize data from another GPU device to current device.") .def( "DeviceToHost", - py::overload_cast &, bool>( + py::overload_cast &, bool>( &StateVectorCudaMPI::CopyGpuDataToHost, py::const_), "Synchronize data from the GPU device to host.") .def( @@ -1629,8 +1634,9 @@ void StateVectorCudaMPI_class_bindings(py::module &m) { } } - return OpsData{ops_name, conv_params, ops_wires, - ops_inverses, conv_matrices}; + return OpsData>{ + ops_name, conv_params, ops_wires, ops_inverses, + conv_matrices}; }) .def("adjoint_jacobian", &AdjointJacobianGPUMPI &sv, const std::vector>> &observables, - const Pennylane::Algorithms::OpsData &operations, + const Pennylane::Algorithms::OpsData< + StateVectorCudaManaged> &operations, const std::vector &trainableParams) { std::vector> jac( observables.size(), @@ -1655,7 +1662,8 @@ void StateVectorCudaMPI_class_bindings(py::module &m) { const StateVectorCudaMPI &sv, const std::vector>> &observables, - const Pennylane::Algorithms::OpsData &operations, + const Pennylane::Algorithms::OpsData< + StateVectorCudaManaged> &operations, const std::vector &trainableParams) { std::vector> jac( observables.size(), diff --git a/pennylane_lightning_gpu/src/simulator/CMakeLists.txt b/pennylane_lightning_gpu/src/simulator/CMakeLists.txt index 087fd0ec..38ac6550 100644 --- a/pennylane_lightning_gpu/src/simulator/CMakeLists.txt +++ b/pennylane_lightning_gpu/src/simulator/CMakeLists.txt @@ -17,7 +17,7 @@ add_library(lightning_gpu_simulator STATIC ${SIMULATOR_FILES}) get_filename_component(CUSTATEVEC_INC_DIR ${CUSTATEVEC_INC} DIRECTORY) target_include_directories(lightning_gpu_simulator PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CUDA_INCLUDE_DIRS} ${CUSTATEVEC_INC_DIR}) -target_link_libraries(lightning_gpu_simulator PUBLIC lightning_simulator lightning_gates lightning_utils lightning_gpu_utils ) +target_link_libraries(lightning_gpu_simulator PUBLIC lightning_qubit lightning_gates lightning_utils lightning_gpu_utils) target_link_libraries(lightning_gpu_simulator PUBLIC ${CUDA_SHARED_RT} ${CUSTATEVEC_LIB}) set_target_properties(lightning_gpu_simulator PROPERTIES POSITION_INDEPENDENT_CODE ON) diff --git a/pennylane_lightning_gpu/src/simulator/StateVectorCudaBase.hpp b/pennylane_lightning_gpu/src/simulator/StateVectorCudaBase.hpp index 2c967ea1..d3e8c0f0 100644 --- a/pennylane_lightning_gpu/src/simulator/StateVectorCudaBase.hpp +++ b/pennylane_lightning_gpu/src/simulator/StateVectorCudaBase.hpp @@ -27,12 +27,13 @@ #include "DevTag.hpp" #include "Error.hpp" #include "StateVectorBase.hpp" -#include "StateVectorManagedCPU.hpp" +#include "StateVectorLQubitManaged.hpp" #include "cuda_helpers.hpp" /// @cond DEV namespace { namespace cuUtil = Pennylane::CUDA::Util; +using Pennylane::LightningQubit::StateVectorLQubitManaged; } // namespace /// @endcond @@ -100,7 +101,7 @@ class StateVectorCudaBase : public StateVectorBase { * * @param sv StateVector host data class. */ - inline void CopyHostDataToGpu(const StateVectorManagedCPU &sv, + inline void CopyHostDataToGpu(const StateVectorLQubitManaged &sv, bool async = false) { PL_ABORT_IF_NOT(BaseType::getNumQubits() == sv.getNumQubits(), "Sizes do not match for Host and GPU data"); @@ -170,7 +171,7 @@ class StateVectorCudaBase : public StateVectorBase { * * @param sv StateVector to receive data from device. */ - inline void CopyGpuDataToHost(StateVectorManagedCPU &sv, + inline void CopyGpuDataToHost(StateVectorLQubitManaged &sv, bool async = false) const { PL_ABORT_IF_NOT(BaseType::getNumQubits() == sv.getNumQubits(), "Sizes do not match for Host and GPU data"); diff --git a/pennylane_lightning_gpu/src/simulator/StateVectorCudaMPI.hpp b/pennylane_lightning_gpu/src/simulator/StateVectorCudaMPI.hpp index b0df37d6..4281f2c0 100644 --- a/pennylane_lightning_gpu/src/simulator/StateVectorCudaMPI.hpp +++ b/pennylane_lightning_gpu/src/simulator/StateVectorCudaMPI.hpp @@ -316,7 +316,7 @@ class StateVectorCudaMPI for (size_t i = 0; i < static_cast(num_indices); i++) { int index = indices[i]; - assert(index >= 0); + PL_ASSERT(index >= 0); size_t rankId = static_cast(index) >> BaseType::getNumQubits(); diff --git a/pennylane_lightning_gpu/src/simulator/StateVectorCudaManaged.hpp b/pennylane_lightning_gpu/src/simulator/StateVectorCudaManaged.hpp index 7f8042a4..19440dca 100644 --- a/pennylane_lightning_gpu/src/simulator/StateVectorCudaManaged.hpp +++ b/pennylane_lightning_gpu/src/simulator/StateVectorCudaManaged.hpp @@ -73,6 +73,8 @@ class StateVectorCudaManaged using BaseType = StateVectorCudaBase; public: + using PrecisionT = Precision; + using ComplexT = std::complex; using CFP_t = typename StateVectorCudaBase>::CFP_t; diff --git a/pennylane_lightning_gpu/src/tests/CMakeLists.txt b/pennylane_lightning_gpu/src/tests/CMakeLists.txt index 0c063494..ea219aa3 100644 --- a/pennylane_lightning_gpu/src/tests/CMakeLists.txt +++ b/pennylane_lightning_gpu/src/tests/CMakeLists.txt @@ -33,17 +33,21 @@ if(PLLGPU_ENABLE_OPENMP) find_package(OpenMP REQUIRED) target_link_libraries(runner_gpu INTERFACE OpenMP::OpenMP_CXX) endif() -target_link_libraries(runner_gpu PUBLIC pennylane_lightning_gpu Catch2::Catch2 lightning_simulator) - -target_sources(runner_gpu PRIVATE Test_StateVectorCudaManaged_NonParam.cpp - Test_StateVectorCudaManaged_Param.cpp - Test_AdjointDiffGPU.cpp - Test_ObservablesGPU.cpp - Test_GateCache.cpp - Test_Generators.cpp - Test_DataBuffer.cpp - TestHelpers.hpp -) +target_link_libraries(runner_gpu PUBLIC pennylane_lightning_gpu + Catch2::Catch2 + pennylane_lightning + lightning_algorithms + lightning_gates + lightning_utils) + +target_sources(runner_gpu PRIVATE Test_StateVectorCudaManaged_NonParam.cpp + Test_StateVectorCudaManaged_Param.cpp + Test_AdjointDiffGPU.cpp + Test_ObservablesGPU.cpp + Test_GateCache.cpp + Test_Generators.cpp + Test_DataBuffer.cpp + TestHelpersLGPU.hpp) target_compile_options(runner_gpu PRIVATE "$<$:-Wall>") @@ -58,7 +62,7 @@ if(PLLGPU_ENABLE_MPI) add_executable(mpi_runner ./mpi/mpi_runner_main.cpp) find_package(MPI REQUIRED) target_link_libraries(mpi_runner PUBLIC MPI::MPI_CXX) - target_link_libraries(mpi_runner PUBLIC pennylane_lightning_gpu Catch2::Catch2 lightning_simulator) + target_link_libraries(mpi_runner PUBLIC pennylane_lightning_gpu Catch2::Catch2 lightning_qubit) target_sources(mpi_runner PRIVATE ./mpi/Test_StateVectorCudaMPI_Param.cpp ./mpi/Test_StateVectorCudaMPI_NonParam.cpp ./mpi/Test_MPIManager.cpp diff --git a/pennylane_lightning_gpu/src/tests/TestHelpers.hpp b/pennylane_lightning_gpu/src/tests/TestHelpersLGPU.hpp similarity index 98% rename from pennylane_lightning_gpu/src/tests/TestHelpers.hpp rename to pennylane_lightning_gpu/src/tests/TestHelpersLGPU.hpp index 6948e504..0678e57c 100644 --- a/pennylane_lightning_gpu/src/tests/TestHelpers.hpp +++ b/pennylane_lightning_gpu/src/tests/TestHelpersLGPU.hpp @@ -3,7 +3,7 @@ #include "AdjointDiffGPU.hpp" #include "StateVectorCudaManaged.hpp" -#include "StateVectorManagedCPU.hpp" +#include "StateVectorLQubitManaged.hpp" #include "cuGateCache.hpp" #include "cuGates_host.hpp" #include "cuda_helpers.hpp" @@ -145,7 +145,7 @@ auto createRandomState(RandomEngine &re, size_t num_qubits) */ template struct SVDataGPU { std::size_t num_qubits_; - StateVectorManagedCPU sv; + StateVectorLQubitManaged sv; StateVectorCudaManaged cuda_sv; SVDataGPU() = delete; diff --git a/pennylane_lightning_gpu/src/tests/Test_AdjointDiffGPU.cpp b/pennylane_lightning_gpu/src/tests/Test_AdjointDiffGPU.cpp index a5a17496..b6192c25 100644 --- a/pennylane_lightning_gpu/src/tests/Test_AdjointDiffGPU.cpp +++ b/pennylane_lightning_gpu/src/tests/Test_AdjointDiffGPU.cpp @@ -13,14 +13,19 @@ #include "AdjointDiffGPU.hpp" #include "StateVectorCudaManaged.hpp" #include "TestHelpers.hpp" +#include "TestHelpersLGPU.hpp" #include "Util.hpp" #ifndef _USE_MATH_DEFINES #define _USE_MATH_DEFINES #endif +/// @cond DEV +namespace { using namespace Pennylane::CUDA; using namespace Pennylane::Algorithms; +} // namespace +/// @endcond /** * @brief Tests the constructability of the AdjointDiff.hpp classes. @@ -210,9 +215,9 @@ TEST_CASE("Algorithms::adjointJacobian Op=[RX,RX,RX], Obs=[ZZZ]", std::vector{1}), std::make_shared>("PauliZ", std::vector{2})); - auto ops = OpsData({"RX", "RX", "RX"}, - {{param[0]}, {param[1]}, {param[2]}}, - {{0}, {1}, {2}}, {false, false, false}); + auto ops = OpsData>( + {"RX", "RX", "RX"}, {{param[0]}, {param[1]}, {param[2]}}, + {{0}, {1}, {2}}, {false, false, false}); adj.adjointJacobian(psi.cuda_sv.getData(), psi.cuda_sv.getLength(), jacobian, {obs}, ops, tp, true); @@ -285,13 +290,13 @@ TEST_CASE("AdjointJacobianGPU::adjointJacobian Decomposed Rot gate, non " const auto thetas = Pennylane::Util::linspace(-2 * M_PI, 2 * M_PI, 7); std::unordered_map> expec_results{ - {thetas[0], {0, -9.90819496e-01, 0}}, - {thetas[1], {-8.18996553e-01, 1.62526544e-01, 0}}, - {thetas[2], {-0.203949, 0.48593716, 0}}, - {thetas[3], {0, 1, 0}}, - {thetas[4], {-2.03948985e-01, 4.85937177e-01, 0}}, - {thetas[5], {-8.18996598e-01, 1.62526487e-01, 0}}, - {thetas[6], {0, -9.90819511e-01, 0}}}; + {thetas[0], {0.0, -9.90819496e-01, 0.0}}, + {thetas[1], {-8.18996553e-01, 1.62526544e-01, 0.0}}, + {thetas[2], {-0.203949, 0.48593716, 0.0}}, + {thetas[3], {0.0, 1.0, 0.0}}, + {thetas[4], {-2.03948985e-01, 4.85937177e-01, 0.0}}, + {thetas[5], {-8.18996598e-01, 1.62526487e-01, 0.0}}, + {thetas[6], {0.0, -9.90819511e-01, 0.0}}}; for (const auto &theta : thetas) { std::vector local_params{theta, std::pow(theta, 3), @@ -490,7 +495,8 @@ TEST_CASE("Algorithms::adjointJacobian Op=RX, Obs=Ham[Z0+Z1]", "[Algorithms]") { auto ham = HamiltonianGPU::create({0.3, 0.7}, {obs1, obs2}); - auto ops = OpsData({"RX"}, {{param[0]}}, {{0}}, {false}); + auto ops = OpsData>({"RX"}, {{param[0]}}, + {{0}}, {false}); adj.adjointJacobian(psi.cuda_sv.getData(), psi.cuda_sv.getLength(), jacobian, {ham}, ops, tp, true); @@ -573,6 +579,6 @@ TEST_CASE("AdjointJacobianGPU::AdjointJacobianGPU Test HermitianObs", adj.adjointJacobian(psi.cuda_sv.getData(), psi.cuda_sv.getLength(), jacobian2, {obs2}, ops, t_params, true); - CHECK((jacobian1[0] == PLApprox(jacobian2[0]).margin(1e-7))); + CHECK((jacobian1[0] == Pennylane::PLApprox(jacobian2[0]).margin(1e-7))); } } diff --git a/pennylane_lightning_gpu/src/tests/Test_DataBuffer.cpp b/pennylane_lightning_gpu/src/tests/Test_DataBuffer.cpp index 3811a0a4..0989f66b 100644 --- a/pennylane_lightning_gpu/src/tests/Test_DataBuffer.cpp +++ b/pennylane_lightning_gpu/src/tests/Test_DataBuffer.cpp @@ -16,7 +16,7 @@ #include // cuDoubleComplex #include -#include "TestHelpers.hpp" +#include "TestHelpersLGPU.hpp" using namespace Pennylane; using namespace CUDA; diff --git a/pennylane_lightning_gpu/src/tests/Test_GateCache.cpp b/pennylane_lightning_gpu/src/tests/Test_GateCache.cpp index 16fb7592..828a1e34 100644 --- a/pennylane_lightning_gpu/src/tests/Test_GateCache.cpp +++ b/pennylane_lightning_gpu/src/tests/Test_GateCache.cpp @@ -16,7 +16,7 @@ #include // cuDoubleComplex #include -#include "TestHelpers.hpp" +#include "TestHelpersLGPU.hpp" using namespace Pennylane; using namespace CUDA; diff --git a/pennylane_lightning_gpu/src/tests/Test_Generators.cpp b/pennylane_lightning_gpu/src/tests/Test_Generators.cpp index 6f4bf9a6..04aa6c29 100644 --- a/pennylane_lightning_gpu/src/tests/Test_Generators.cpp +++ b/pennylane_lightning_gpu/src/tests/Test_Generators.cpp @@ -7,7 +7,7 @@ #include "GateGenerators.hpp" #include "StateVectorCudaManaged.hpp" -#include "TestHelpers.hpp" +#include "TestHelpersLGPU.hpp" using namespace Pennylane::CUDA; using namespace Pennylane::CUDA::Generators; diff --git a/pennylane_lightning_gpu/src/tests/Test_ObservablesGPU.cpp b/pennylane_lightning_gpu/src/tests/Test_ObservablesGPU.cpp index 4c949ef1..35554165 100644 --- a/pennylane_lightning_gpu/src/tests/Test_ObservablesGPU.cpp +++ b/pennylane_lightning_gpu/src/tests/Test_ObservablesGPU.cpp @@ -12,7 +12,7 @@ #include "AdjointDiffGPU.hpp" #include "StateVectorCudaManaged.hpp" -#include "TestHelpers.hpp" +#include "TestHelpersLGPU.hpp" #include "Util.hpp" #ifndef _USE_MATH_DEFINES diff --git a/pennylane_lightning_gpu/src/tests/Test_StateVectorCudaManaged_NonParam.cpp b/pennylane_lightning_gpu/src/tests/Test_StateVectorCudaManaged_NonParam.cpp index 7274f58e..cf0f55e2 100644 --- a/pennylane_lightning_gpu/src/tests/Test_StateVectorCudaManaged_NonParam.cpp +++ b/pennylane_lightning_gpu/src/tests/Test_StateVectorCudaManaged_NonParam.cpp @@ -10,12 +10,12 @@ #include #include "StateVectorCudaManaged.hpp" -#include "StateVectorRawCPU.hpp" +#include "StateVectorLQubitRaw.hpp" #include "cuGateCache.hpp" #include "cuGates_host.hpp" #include "cuda_helpers.hpp" -#include "TestHelpers.hpp" +#include "TestHelpersLGPU.hpp" using namespace Pennylane; using namespace CUDA; diff --git a/pennylane_lightning_gpu/src/tests/Test_StateVectorCudaManaged_Param.cpp b/pennylane_lightning_gpu/src/tests/Test_StateVectorCudaManaged_Param.cpp index f800eb2b..da33be9f 100644 --- a/pennylane_lightning_gpu/src/tests/Test_StateVectorCudaManaged_Param.cpp +++ b/pennylane_lightning_gpu/src/tests/Test_StateVectorCudaManaged_Param.cpp @@ -9,16 +9,22 @@ #include +#include "Gates.hpp" +#include "TestHelpers.hpp" + #include "StateVectorCudaManaged.hpp" -#include "StateVectorRawCPU.hpp" +#include "StateVectorLQubitRaw.hpp" +#include "TestHelpersLGPU.hpp" #include "cuGateCache.hpp" #include "cuGates_host.hpp" #include "cuda_helpers.hpp" -#include "TestHelpers.hpp" - +/// @cond DEV +namespace { using namespace Pennylane; using namespace CUDA; +} // namespace +/// @endcond TEMPLATE_TEST_CASE("LightningGPU::applyRX", "[LightningGPU_Param]", double) { using cp_t = std::complex; @@ -172,7 +178,7 @@ TEMPLATE_TEST_CASE("LightningGPU::applyRZ", "[LightningGPU_Param]", float, std::vector> rz_data; rz_data.reserve(angles.size()); for (auto &a : angles) { - rz_data.push_back(Gates::getRZ(a)); + rz_data.push_back(Gates::getRZ(a)); } std::vector> expected_results = { @@ -236,7 +242,7 @@ TEMPLATE_TEST_CASE("LightningGPU::applyPhaseShift", "[LightningGPU_Param]", std::vector> ps_data; ps_data.reserve(angles.size()); for (auto &a : angles) { - ps_data.push_back(Gates::getPhaseShift(a)); + ps_data.push_back(Gates::getPhaseShift(a)); } std::vector> expected_results = { @@ -300,7 +306,7 @@ TEMPLATE_TEST_CASE("LightningGPU::applyControlledPhaseShift", std::vector> ps_data; ps_data.reserve(angles.size()); for (auto &a : angles) { - ps_data.push_back(Gates::getPhaseShift(a)); + ps_data.push_back(Gates::getPhaseShift(a)); } std::vector> expected_results = { @@ -350,8 +356,8 @@ TEMPLATE_TEST_CASE("LightningGPU::applyRot", "[LightningGPU_Param]", float, std::vector(0b1 << num_qubits)}; for (size_t i = 0; i < angles.size(); i++) { - const auto rot_mat = - Gates::getRot(angles[i][0], angles[i][1], angles[i][2]); + const auto rot_mat = Gates::getRot( + angles[i][0], angles[i][1], angles[i][2]); expected_results[i][0] = rot_mat[0]; expected_results[i][0b1 << (num_qubits - i - 1)] = rot_mat[2]; } @@ -389,7 +395,7 @@ TEMPLATE_TEST_CASE("LightningGPU::applyCRot", "[LightningGPU_Param]", float, std::vector expected_results(8); const auto rot_mat = - Gates::getRot(angles[0], angles[1], angles[2]); + Gates::getRot(angles[0], angles[1], angles[2]); expected_results[0b1 << (num_qubits - 1)] = rot_mat[0]; expected_results[(0b1 << num_qubits) - 2] = rot_mat[2]; diff --git a/pennylane_lightning_gpu/src/tests/mpi/Test_MPIManager.cpp b/pennylane_lightning_gpu/src/tests/mpi/Test_MPIManager.cpp index 805a5cef..4c75e1dd 100644 --- a/pennylane_lightning_gpu/src/tests/mpi/Test_MPIManager.cpp +++ b/pennylane_lightning_gpu/src/tests/mpi/Test_MPIManager.cpp @@ -10,7 +10,7 @@ #include "MPIManager.hpp" -#include "../TestHelpers.hpp" +#include "../TestHelpersLGPU.hpp" using namespace Pennylane; using namespace Pennylane::MPI; diff --git a/pennylane_lightning_gpu/src/tests/mpi/Test_MPI_AdjointDiffGPU.cpp b/pennylane_lightning_gpu/src/tests/mpi/Test_MPI_AdjointDiffGPU.cpp index 4776e7c2..63de9846 100644 --- a/pennylane_lightning_gpu/src/tests/mpi/Test_MPI_AdjointDiffGPU.cpp +++ b/pennylane_lightning_gpu/src/tests/mpi/Test_MPI_AdjointDiffGPU.cpp @@ -10,7 +10,7 @@ #include -#include "../TestHelpers.hpp" +#include "../TestHelpersLGPU.hpp" #include "AdjointDiffGPUMPI.hpp" #include "StateVectorCudaMPI.hpp" #include "Util.hpp" diff --git a/pennylane_lightning_gpu/src/tests/mpi/Test_StateVectorCudaMPI_NonParam.cpp b/pennylane_lightning_gpu/src/tests/mpi/Test_StateVectorCudaMPI_NonParam.cpp index 3a426c7b..4265005a 100644 --- a/pennylane_lightning_gpu/src/tests/mpi/Test_StateVectorCudaMPI_NonParam.cpp +++ b/pennylane_lightning_gpu/src/tests/mpi/Test_StateVectorCudaMPI_NonParam.cpp @@ -15,11 +15,11 @@ #include "StateVectorCudaMPI.hpp" #include "StateVectorCudaManaged.hpp" -#include "StateVectorRawCPU.hpp" +#include "StateVectorLQubitRaw.hpp" #include "MPIManager.hpp" -#include "../TestHelpers.hpp" +#include "../TestHelpersLGPU.hpp" using namespace Pennylane; using namespace Pennylane::MPI; diff --git a/pennylane_lightning_gpu/src/tests/mpi/Test_StateVectorCudaMPI_Param.cpp b/pennylane_lightning_gpu/src/tests/mpi/Test_StateVectorCudaMPI_Param.cpp index 129baac6..a960ea76 100644 --- a/pennylane_lightning_gpu/src/tests/mpi/Test_StateVectorCudaMPI_Param.cpp +++ b/pennylane_lightning_gpu/src/tests/mpi/Test_StateVectorCudaMPI_Param.cpp @@ -15,11 +15,11 @@ #include "StateVectorCudaMPI.hpp" #include "StateVectorCudaManaged.hpp" -#include "StateVectorRawCPU.hpp" +#include "StateVectorLQubitRaw.hpp" #include "MPIManager.hpp" -#include "../TestHelpers.hpp" +#include "../TestHelpersLGPU.hpp" using namespace Pennylane; using namespace Pennylane::MPI; diff --git a/requirements.txt b/requirements.txt index 1b51bd0b..b14ea179 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -pip~=22.0 +pip==23.0 ninja cmake custatevec-cu11 @@ -9,3 +9,5 @@ pybind11 pytest pytest-cov pytest-mock +black==23.7.0 +clang-format==14 \ No newline at end of file diff --git a/setup.py b/setup.py index c4711633..94ee520a 100644 --- a/setup.py +++ b/setup.py @@ -132,7 +132,6 @@ def build_extension(self, ext: CMakeExtension): "Operating System :: POSIX :: Linux", "Programming Language :: Python", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", diff --git a/tests/test_adjoint_jacobian.py b/tests/test_adjoint_jacobian.py index 40d464fc..adef270a 100644 --- a/tests/test_adjoint_jacobian.py +++ b/tests/test_adjoint_jacobian.py @@ -91,7 +91,7 @@ class TestAdjointJacobian: """Tests for the adjoint_jacobian method""" from pennylane_lightning_gpu import LightningGPU as lg - from pennylane_lightning import LightningQubit as lq + from pennylane_lightning.lightning_qubit import LightningQubit as lq @pytest.fixture def dev_gpu(self): @@ -192,11 +192,12 @@ def test_unsupported_hermitian_expectation(self, dev_gpu): @pytest.mark.parametrize("theta", np.linspace(-2 * np.pi, 2 * np.pi, 7)) @pytest.mark.parametrize("G", [qml.RX, qml.RY, qml.RZ]) - def test_pauli_rotation_gradient(self, G, theta, tol, dev_cpu, dev_gpu): + @pytest.mark.parametrize("stateprep", [qml.QubitStateVector, qml.StatePrep]) + def test_pauli_rotation_gradient(self, stateprep, G, theta, tol, dev_cpu, dev_gpu): """Tests that the automatic gradients of Pauli rotations are correct.""" with qml.tape.QuantumTape() as tape: - qml.QubitStateVector(np.array([1.0, -1.0]) / np.sqrt(2), wires=0) + stateprep(np.array([1.0, -1.0]) / np.sqrt(2), wires=0) G(theta, wires=[0]) qml.expval(qml.PauliZ(0)) @@ -208,13 +209,14 @@ def test_pauli_rotation_gradient(self, G, theta, tol, dev_cpu, dev_gpu): assert np.allclose(calculated_val, expected_val, atol=tol, rtol=0) @pytest.mark.parametrize("theta", np.linspace(-2 * np.pi, 2 * np.pi, 7)) - def test_Rot_gradient(self, theta, tol, dev_cpu, dev_gpu): + @pytest.mark.parametrize("stateprep", [qml.QubitStateVector, qml.StatePrep]) + def test_Rot_gradient(self, stateprep, theta, tol, dev_cpu, dev_gpu): """Tests that the device gradient of an arbitrary Euler-angle-parameterized gate is correct.""" params = np.array([theta, theta**3, np.sqrt(2) * theta]) with qml.tape.QuantumTape() as tape: - qml.QubitStateVector(np.array([1.0, -1.0]) / np.sqrt(2), wires=0) + stateprep(np.array([1.0, -1.0]) / np.sqrt(2), wires=0) qml.Rot(*params, wires=[0]) qml.expval(qml.PauliZ(0)) @@ -687,7 +689,7 @@ def circuit_2(params, wires): def circuit_ansatz(params, wires): """Circuit ansatz containing all the parametrized gates""" - qml.QubitStateVector(unitary_group.rvs(2**4, random_state=0)[0], wires=wires) + qml.StatePrep(unitary_group.rvs(2**4, random_state=0)[0], wires=wires) qml.RX(params[0], wires=wires[0]) qml.RY(params[1], wires=wires[1]) qml.adjoint(qml.RX(params[2], wires=wires[2])) diff --git a/tests/test_apply.py b/tests/test_apply.py index df481f55..36846cc1 100644 --- a/tests/test_apply.py +++ b/tests/test_apply.py @@ -220,19 +220,19 @@ def test_apply_operation_three_wires_no_parameters( @pytest.mark.parametrize( "operation,expected_output,par", [ - (qml.BasisState, [0, 0, 1, 0], [1, 0]), (qml.BasisState, [0, 0, 1, 0], [1, 0]), (qml.BasisState, [0, 0, 0, 1], [1, 1]), (qml.QubitStateVector, [0, 0, 1, 0], [0, 0, 1, 0]), - (qml.QubitStateVector, [0, 0, 1, 0], [0, 0, 1, 0]), (qml.QubitStateVector, [0, 0, 0, 1], [0, 0, 0, 1]), + (qml.StatePrep, [0, 0, 1, 0], [0, 0, 1, 0]), + (qml.StatePrep, [0, 0, 0, 1], [0, 0, 0, 1]), ( - qml.QubitStateVector, + qml.StatePrep, [1 / math.sqrt(3), 0, 1 / math.sqrt(3), 1 / math.sqrt(3)], [1 / math.sqrt(3), 0, 1 / math.sqrt(3), 1 / math.sqrt(3)], ), ( - qml.QubitStateVector, + qml.StatePrep, [1 / math.sqrt(3), 0, -1 / math.sqrt(3), 1 / math.sqrt(3)], [1 / math.sqrt(3), 0, -1 / math.sqrt(3), 1 / math.sqrt(3)], ), @@ -477,27 +477,28 @@ def test_apply_operation_two_wires_with_parameters( assert np.allclose(state_vector, np.array(expected_output), atol=tol, rtol=0) - def test_apply_errors_qubit_state_vector(self, qubit_device_2_wires): + @pytest.mark.parametrize("stateprep", [qml.QubitStateVector, qml.StatePrep]) + def test_apply_errors_qubit_state_vector(self, stateprep, qubit_device_2_wires): """Test that apply fails for incorrect state preparation, and > 2 qubit gates""" with pytest.raises(ValueError, match="Sum of amplitudes-squared does not equal one."): - qubit_device_2_wires.apply([qml.QubitStateVector(np.array([1, -1]), wires=[0])]) + qubit_device_2_wires.apply([stateprep(np.array([1, -1]), wires=[0])]) with pytest.raises( ValueError, match=r"State vector must have shape \(2\*\*wires,\) or \(batch_size, 2\*\*wires\).", ): p = np.array([1, 0, 1, 1, 0]) / np.sqrt(3) - qubit_device_2_wires.apply([qml.QubitStateVector(p, wires=[0, 1])]) + qubit_device_2_wires.apply([stateprep(p, wires=[0, 1])]) with pytest.raises( DeviceError, - match="Operation QubitStateVector cannot be used after other Operations have already been applied ", + match=f"Operation {stateprep(np.array([0, 1, 0, 0]), wires=[0, 1]).name} cannot be used after other Operations have already been applied ", ): qubit_device_2_wires.reset() qubit_device_2_wires.apply( [ qml.RZ(0.5, wires=[0]), - qml.QubitStateVector(np.array([0, 1, 0, 0]), wires=[0, 1]), + stateprep(np.array([0, 1, 0, 0]), wires=[0, 1]), ] ) @@ -545,8 +546,9 @@ class TestExpval: (qml.Identity, [1 / math.sqrt(2), -1 / math.sqrt(2)], 1), ], ) + @pytest.mark.parametrize("stateprep", [qml.QubitStateVector, qml.StatePrep]) def test_expval_single_wire_no_parameters( - self, qubit_device_1_wire, tol, operation, input, expected_output + self, stateprep, qubit_device_1_wire, tol, operation, input, expected_output ): """Tests that expectation values are properly calculated for single-wire observables without parameters.""" @@ -554,7 +556,7 @@ def test_expval_single_wire_no_parameters( qubit_device_1_wire.reset() qubit_device_1_wire.apply( - [qml.QubitStateVector(np.array(input), wires=[0])], + [stateprep(np.array(input), wires=[0])], rotations=obs.diagonalizing_gates(), ) res = qubit_device_1_wire.expval(obs) @@ -585,8 +587,9 @@ class TestVar: (qml.Identity, [1 / math.sqrt(2), -1 / math.sqrt(2)], 0), ], ) + @pytest.mark.parametrize("stateprep", [qml.QubitStateVector, qml.StatePrep]) def test_var_single_wire_no_parameters( - self, qubit_device_1_wire, tol, operation, input, expected_output + self, stateprep, qubit_device_1_wire, tol, operation, input, expected_output ): """Tests that variances are properly calculated for single-wire observables without parameters.""" @@ -594,7 +597,7 @@ def test_var_single_wire_no_parameters( qubit_device_1_wire.reset() qubit_device_1_wire.apply( - [qml.QubitStateVector(np.array(input), wires=[0])], + [stateprep(np.array(input), wires=[0])], rotations=obs.diagonalizing_gates(), ) res = qubit_device_1_wire.var(obs) @@ -749,8 +752,9 @@ def circuit(): ("CZ", [-1 / 2, -1 / 2]), ], ) + @pytest.mark.parametrize("stateprep", [qml.QubitStateVector, qml.StatePrep]) def test_supported_gate_two_wires_no_parameters( - self, qubit_device_2_wires, tol, name, expected_output + self, stateprep, qubit_device_2_wires, tol, name, expected_output ): """Tests supported gates that act on two wires that are not parameterized""" @@ -759,7 +763,7 @@ def test_supported_gate_two_wires_no_parameters( @qml.qnode(qubit_device_2_wires) def circuit(): - qml.QubitStateVector(np.array([1 / 2, 0, 0, math.sqrt(3) / 2]), wires=[0, 1]) + stateprep(np.array([1 / 2, 0, 0, math.sqrt(3) / 2]), wires=[0, 1]) op(wires=[0, 1]) return qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliZ(1)) @@ -799,9 +803,9 @@ def circuit(): ("BasisState", [0, 0], [1, 1]), ("BasisState", [1, 0], [-1, 1]), ("BasisState", [0, 1], [1, -1]), - ("QubitStateVector", [1, 0, 0, 0], [1, 1]), - ("QubitStateVector", [0, 0, 1, 0], [-1, 1]), - ("QubitStateVector", [0, 1, 0, 0], [1, -1]), + ("StatePrep", [1, 0, 0, 0], [1, 1]), + ("StatePrep", [0, 0, 1, 0], [-1, 1]), + ("StatePrep", [0, 1, 0, 0], [1, -1]), ], ) def test_supported_state_preparation( @@ -847,11 +851,11 @@ def circuit(): @pytest.mark.parametrize( "name,par,wires,expected_output", [ - ("QubitStateVector", [0, 1], [1], [1, -1]), - ("QubitStateVector", [0, 1], [0], [-1, 1]), - ("QubitStateVector", [1.0 / np.sqrt(2), 1.0 / np.sqrt(2)], [1], [1, 0]), - ("QubitStateVector", [1j / 2.0, np.sqrt(3) / 2.0], [1], [1, -0.5]), - ("QubitStateVector", [(2 - 1j) / 3.0, 2j / 3.0], [0], [1 / 9.0, 1]), + ("StatePrep", [0, 1], [1], [1, -1]), + ("StatePrep", [0, 1], [0], [-1, 1]), + ("StatePrep", [1.0 / np.sqrt(2), 1.0 / np.sqrt(2)], [1], [1, 0]), + ("StatePrep", [1j / 2.0, np.sqrt(3) / 2.0], [1], [1, -0.5]), + ("StatePrep", [(2 - 1j) / 3.0, 2j / 3.0], [0], [1 / 9.0, 1]), ], ) def test_state_vector_2_qubit_subset( @@ -875,7 +879,7 @@ def circuit(): "name,par,wires,expected_output", [ ( - "QubitStateVector", + "StatePrep", [ 1j / np.sqrt(10), (1 - 2j) / np.sqrt(10), @@ -890,32 +894,32 @@ def circuit(): [1 / 5.0, 1.0, -4 / 5.0], ), ( - "QubitStateVector", + "StatePrep", [1 / np.sqrt(2), 0, 0, 1 / np.sqrt(2)], [0, 2], [0.0, 1.0, 0.0], ), ( - "QubitStateVector", + "StatePrep", [1 / np.sqrt(2), 0, 0, 1 / np.sqrt(2)], [0, 1], [0.0, 0.0, 1.0], ), - ("QubitStateVector", [0, 1, 0, 0, 0, 0, 0, 0], [2, 1, 0], [-1.0, 1.0, 1.0]), + ("StatePrep", [0, 1, 0, 0, 0, 0, 0, 0], [2, 1, 0], [-1.0, 1.0, 1.0]), ( - "QubitStateVector", + "StatePrep", [0, 1j, 0, 0, 0, 0, 0, 0], [0, 2, 1], [1.0, -1.0, 1.0], ), ( - "QubitStateVector", + "StatePrep", [0, 1 / np.sqrt(2), 0, 1 / np.sqrt(2)], [1, 0], [-1.0, 0.0, 1.0], ), ( - "QubitStateVector", + "StatePrep", [0, 1 / np.sqrt(2), 0, 1 / np.sqrt(2)], [0, 1], [0.0, -1.0, 1.0], @@ -1032,7 +1036,7 @@ def test_supported_gate_two_wires_with_parameters( @qml.qnode(qubit_device_2_wires) def circuit(): - qml.QubitStateVector(np.array([1 / 2, 0, 0, math.sqrt(3) / 2]), wires=[0, 1]) + qml.StatePrep(np.array([1 / 2, 0, 0, math.sqrt(3) / 2]), wires=[0, 1]) op(*par, wires=[0, 1]) return qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliZ(1)) @@ -1066,7 +1070,7 @@ def test_supported_observable_single_wire_no_parameters( @qml.qnode(qubit_device_1_wire) def circuit(): - qml.QubitStateVector(np.array(state), wires=[0]) + qml.StatePrep(np.array(state), wires=[0]) return qml.expval(obs(wires=[0])) assert np.isclose(circuit(), expected_output, atol=tol, rtol=0) @@ -1090,7 +1094,7 @@ def test_supported_observable_single_wire_with_parameters( @qml.qnode(qubit_device_1_wire) def circuit(): - qml.QubitStateVector(np.array(state), wires=[0]) + qml.StatePrep(np.array(state), wires=[0]) return qml.expval(obs(*par, wires=[0])) assert np.isclose(circuit(), expected_output, atol=tol, rtol=0) diff --git a/tests/test_comparison.py b/tests/test_comparison.py index dda4a89c..be23b165 100644 --- a/tests/test_comparison.py +++ b/tests/test_comparison.py @@ -67,7 +67,7 @@ def one_qubit_block(wires=None): qml.PauliX(wires=wires) -@pytest.mark.usefixtures("lightning_qubit_dev", "lightning_gpu_qubit_dev") +@pytest.mark.usefixtures("default_qubit_dev", "lightning_gpu_qubit_dev") class TestComparison: """A test that compares the output states of ``lightning.gpu`` and ``default.qubit`` for a variety of different circuits. This uses ``default.qubit`` as a gold standard to compare @@ -76,7 +76,7 @@ class TestComparison: @pytest.mark.parametrize("basis_state", itertools.product(*[(0, 1)] * 1)) @pytest.mark.parametrize("wires", [1]) def test_one_qubit_circuit( - self, wires, lightning_qubit_dev, lightning_gpu_qubit_dev, basis_state + self, wires, default_qubit_dev, lightning_gpu_qubit_dev, basis_state ): """Test a single-qubit circuit""" @@ -87,11 +87,11 @@ def circuit(): one_qubit_block(wires=0) return qml.expval(qml.PauliZ(0)) - lightning = qml.QNode(circuit, lightning_qubit_dev) + default = qml.QNode(circuit, default_qubit_dev) lightninggpu = qml.QNode(circuit, lightning_gpu_qubit_dev) - lightning() - lightning_state = lightning_qubit_dev.state + default() + default_state = default_qubit_dev.state lightninggpu() @@ -100,12 +100,12 @@ def circuit(): ) lightning_gpu_qubit_dev.syncD2H(lightninggpu_state) # Copy GPU data to CPU - assert np.allclose(lightning_state, lightninggpu_state) + assert np.allclose(default_state, lightninggpu_state) @pytest.mark.parametrize("basis_state", itertools.product(*[(0, 1)] * 2)) @pytest.mark.parametrize("wires", [2]) def test_two_qubit_circuit( - self, wires, lightning_qubit_dev, lightning_gpu_qubit_dev, basis_state + self, wires, default_qubit_dev, lightning_gpu_qubit_dev, basis_state ): """Test a two-qubit circuit""" @@ -126,11 +126,11 @@ def circuit(): qml.CRot(0.2, 0.3, 0.7, wires=[0, 1]) return qml.expval(qml.PauliZ(0)) - lightning = qml.QNode(circuit, lightning_qubit_dev) + default = qml.QNode(circuit, default_qubit_dev) lightninggpu = qml.QNode(circuit, lightning_gpu_qubit_dev) - lightning() - lightning_state = lightning_qubit_dev.state + default() + default_state = default_qubit_dev.state lightninggpu() lightninggpu_state = np.zeros(2**lightning_gpu_qubit_dev.num_wires).astype( @@ -138,12 +138,12 @@ def circuit(): ) lightning_gpu_qubit_dev.syncD2H(lightninggpu_state) # Copy GPU data to CPU - assert np.allclose(lightning_state, lightninggpu_state) + assert np.allclose(default_state, lightninggpu_state) @pytest.mark.parametrize("basis_state", itertools.product(*[(0, 1)] * 3)) @pytest.mark.parametrize("wires", [3]) def test_three_qubit_circuit( - self, wires, lightning_qubit_dev, lightning_gpu_qubit_dev, basis_state + self, wires, default_qubit_dev, lightning_gpu_qubit_dev, basis_state ): """Test a three-qubit circuit""" @@ -172,11 +172,11 @@ def circuit(): qml.Toffoli(wires=[2, 1, 0]) return qml.expval(qml.PauliZ(0)) - lightning = qml.QNode(circuit, lightning_qubit_dev) + default = qml.QNode(circuit, default_qubit_dev) lightninggpu = qml.QNode(circuit, lightning_gpu_qubit_dev) - lightning() - lightning_state = lightning_qubit_dev.state + default() + default_state = default_qubit_dev.state lightninggpu() lightninggpu_state = np.zeros(2**lightning_gpu_qubit_dev.num_wires).astype( @@ -184,12 +184,12 @@ def circuit(): ) lightning_gpu_qubit_dev.syncD2H(lightninggpu_state) # Copy GPU data to CPU - assert np.allclose(lightning_state, lightninggpu_state) + assert np.allclose(default_state, lightninggpu_state) @pytest.mark.parametrize("basis_state", itertools.product(*[(0, 1)] * 4)) @pytest.mark.parametrize("wires", [4]) def test_four_qubit_circuit( - self, wires, lightning_qubit_dev, lightning_gpu_qubit_dev, basis_state + self, wires, default_qubit_dev, lightning_gpu_qubit_dev, basis_state ): """Test a four-qubit circuit""" @@ -223,11 +223,11 @@ def circuit(): qml.Toffoli(wires=[2, 1, 0]) return qml.expval(qml.PauliZ(0)) - lightning = qml.QNode(circuit, lightning_qubit_dev) + default = qml.QNode(circuit, default_qubit_dev) lightninggpu = qml.QNode(circuit, lightning_gpu_qubit_dev) - lightning() - lightning_state = lightning_qubit_dev.state + default() + default_state = default_qubit_dev.state lightninggpu() lightninggpu_state = np.zeros(2**lightning_gpu_qubit_dev.num_wires).astype( @@ -235,28 +235,29 @@ def circuit(): ) lightning_gpu_qubit_dev.syncD2H(lightninggpu_state) # Copy GPU data to CPU - assert np.allclose(lightning_state, lightninggpu_state) + assert np.allclose(default_state, lightninggpu_state) @pytest.mark.parametrize("wires", range(1, 17)) - def test_n_qubit_circuit(self, wires, lightning_qubit_dev, lightning_gpu_qubit_dev): + @pytest.mark.parametrize("stateprep", [qml.QubitStateVector, qml.StatePrep]) + def test_n_qubit_circuit(self, stateprep, wires, default_qubit_dev, lightning_gpu_qubit_dev): """Test an n-qubit circuit""" - vec = np.array([1] * (2**wires)) / np.sqrt(2**wires) + vec = np.array([1 + 0.0j] * (2**wires)) / np.sqrt(2**wires) shape = qml.StronglyEntanglingLayers.shape(2, wires) w = np.random.uniform(high=2 * np.pi, size=shape) def circuit(): """Prepares the equal superposition state and then applies StronglyEntanglingLayers and concludes with a simple PauliZ measurement""" - qml.QubitStateVector(vec, wires=range(wires)) + stateprep(vec, wires=range(wires)) qml.StronglyEntanglingLayers(w, wires=range(wires)) return qml.expval(qml.PauliZ(0)) - lightning = qml.QNode(circuit, lightning_qubit_dev) + default = qml.QNode(circuit, default_qubit_dev) lightninggpu = qml.QNode(circuit, lightning_gpu_qubit_dev) - lightning() - lightning_state = lightning_qubit_dev.state + default() + default_state = default_qubit_dev.state lightninggpu() lightninggpu_state = np.zeros(2**lightning_gpu_qubit_dev.num_wires).astype( @@ -264,4 +265,4 @@ def circuit(): ) lightning_gpu_qubit_dev.syncD2H(lightninggpu_state) # Copy GPU data to CPU - assert np.allclose(lightning_state, lightninggpu_state) + assert np.allclose(default_state, lightninggpu_state) diff --git a/tests/test_gates.py b/tests/test_gates.py index 254ac5ee..856d2746 100644 --- a/tests/test_gates.py +++ b/tests/test_gates.py @@ -96,7 +96,7 @@ def test_gate_unitary_correct(op, op_name): """Test if lightning.gpu correctly applies gates by reconstructing the unitary matrix and comparing to the expected version""" - if op_name in ("BasisState", "QubitStateVector"): + if op_name in ("BasisState", "QubitStateVector", "StatePrep"): pytest.skip("Skipping operation because it is a state preparation") if op == None: @@ -131,7 +131,7 @@ def test_inverse_unitary_correct(op, op_name): """Test if lightning.gpu correctly applies inverse gates by reconstructing the unitary matrix and comparing to the expected version""" - if op_name in ("BasisState", "QubitStateVector"): + if op_name in ("BasisState", "QubitStateVector", "StatePrep"): pytest.skip("Skipping operation because it is a state preparation") if op == None: pytest.skip("Skipping operation.")