Skip to content

Commit

Permalink
Add Clifford-only simulator (Stim) (#2235)
Browse files Browse the repository at this point in the history
* Add Clifford-only simulator (Stim) (#2193)

* Constrain x86-64 build to AVX2

* Compilation update for #2168

---------

Co-authored-by: Thien Nguyen <[email protected]>
  • Loading branch information
bmhowe23 and 1tnguyen authored Oct 1, 2024
1 parent 5bebaf2 commit 81c482b
Show file tree
Hide file tree
Showing 35 changed files with 542 additions and 11 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,6 @@
path = tpls/Crow
url = https://github.com/CrowCpp/Crow.git
ignore = dirty
[submodule "tpls/Stim"]
path = tpls/Stim
url = https://github.com/quantumlib/Stim
8 changes: 8 additions & 0 deletions NOTICE
Original file line number Diff line number Diff line change
Expand Up @@ -172,3 +172,11 @@ Tweedledum - MIT License
License at <https://github.com/boschmitt/tweedledum/blob/master/LICENSE>

----------------------------------------------------------------

Stim - Apache License 2.0
<https://github.com/quantumlib/Stim>

The incorporated source code and its license can be found as a submodule on the CUDA-Q repository.
License at <https://github.com/quantumlib/Stim/blob/main/LICENSE>

----------------------------------------------------------------
1 change: 1 addition & 0 deletions docs/sphinx/using/backends/backends.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ CUDA-Q Backends
* :ref:`qpp-cpu <qpp-cpu-backend>`
* :ref:`quantinuum <quantinuum-backend>`
* :ref:`remote-mqpu <mqpu-platform>`
* :ref:`stim <stim-backend>`
* :ref:`tensornet <tensor-backends>`
* :ref:`tensornet-mps <tensor-backends>`

Expand Down
34 changes: 34 additions & 0 deletions docs/sphinx/using/backends/simulators.rst
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,40 @@ use the following commands:
./program.x
Clifford-Only Simulation (CPU)
++++++++++++++++++++++++++++++++++

.. _stim-backend:

This target provides a fast simulator for circuits containing *only* Clifford
gates. Any non-Clifford gates (such as T gates and Toffoli gates) are not
supported. This simulator is based on the `Stim <https://github.com/quantumlib/Stim>`_
library.

To execute a program on the :code:`stim` target, use the following commands:

.. tab:: Python

.. code:: bash
python3 program.py [...] --target stim
The target can also be defined in the application code by calling

.. code:: python
cudaq.set_target('stim')
If a target is set in the application code, this target will override the :code:`--target` command line flag given during program invocation.

.. tab:: C++

.. code:: bash
nvq++ --target stim program.cpp [...] -o program.x
./program.x
Tensor Network Simulators
==================================

Expand Down
91 changes: 91 additions & 0 deletions python/tests/backends/test_stim.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# ============================================================================ #
# Copyright (c) 2022 - 2024 NVIDIA Corporation & Affiliates. #
# All rights reserved. #
# #
# This source code and the accompanying materials are made available under #
# the terms of the Apache License 2.0 which accompanies this distribution. #
# ============================================================================ #

import os
from typing import List
import pytest

import cudaq
import numpy as np


@pytest.fixture(scope="session", autouse=True)
def setTarget():
old_target = cudaq.get_target()
cudaq.set_target('stim')
yield
cudaq.set_target(old_target)


def test_stim_non_clifford():

@cudaq.kernel
def kernel():
qubits = cudaq.qvector(10)
rx(0.1, qubits[0])

with pytest.raises(RuntimeError) as e:
# Cannot perform non-Clifford gates in Stim simulator
cudaq.sample(kernel)


def test_stim_toffoli_gates():

@cudaq.kernel
def kernel():
qubits = cudaq.qvector(10)
cx(qubits[0:9], qubits[9])

with pytest.raises(RuntimeError) as e:
# Cannot perform Toffoli gates in Stim simulator
cudaq.sample(kernel)


def test_stim_sample():
# Create the kernel we'd like to execute on Stim
@cudaq.kernel
def kernel():
qubits = cudaq.qvector(250)
h(qubits[0])
# Stim is a Clifford-only simulator, so it can do many qubits.
for i in range(1, 250):
cx(qubits[i - 1], qubits[i])
mz(qubits)

counts = cudaq.sample(kernel)
assert (len(counts) == 2)
assert ('0' * 250 in counts)
assert ('1' * 250 in counts)


def test_stim_state_preparation():

@cudaq.kernel
def kernel(vec: List[complex]):
qubits = cudaq.qvector(vec)

with pytest.raises(RuntimeError) as e:
# Cannot initialize qubits from state data in this simulator
state = [1. / np.sqrt(2.), 1. / np.sqrt(2.), 0., 0.]
cudaq.sample(kernel, state)


def test_stim_state_preparation_builder():
kernel, state = cudaq.make_kernel(List[complex])
qubits = kernel.qalloc(state)

with pytest.raises(RuntimeError) as e:
# Cannot initialize qubits from state data in this simulator
state = [1. / np.sqrt(2.), 1. / np.sqrt(2.), 0., 0.]
cudaq.sample(kernel, state)


# leave for gdb debugging
if __name__ == "__main__":
loc = os.path.abspath(__file__)
pytest.main([loc, "-s"])
1 change: 1 addition & 0 deletions runtime/nvqir/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ install(TARGETS ${LIBRARY_NAME}
INCLUDES DESTINATION include/nvqir)

add_subdirectory(qpp)
add_subdirectory(stim)

if (CUSTATEVEC_ROOT AND CUDA_FOUND)
add_subdirectory(custatevec)
Expand Down
12 changes: 11 additions & 1 deletion runtime/nvqir/CircuitSimulator.h
Original file line number Diff line number Diff line change
Expand Up @@ -752,7 +752,17 @@ class CircuitSimulatorBase : public CircuitSimulator {
summaryData.svGateUpdate(
next.controls.size(), next.targets.size(), stateDimension,
stateDimension * sizeof(std::complex<ScalarType>));
applyGate(next);
try {
applyGate(next);
} catch (std::exception &e) {
while (!gateQueue.empty())
gateQueue.pop();
throw e;
} catch (...) {
while (!gateQueue.empty())
gateQueue.pop();
throw std::runtime_error("Unknown exception in applyGate");
}
if (executionContext && executionContext->noiseModel) {
std::vector<double> params(next.parameters.begin(),
next.parameters.end());
Expand Down
47 changes: 47 additions & 0 deletions runtime/nvqir/stim/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# ============================================================================ #
# Copyright (c) 2022 - 2024 NVIDIA Corporation & Affiliates. #
# All rights reserved. #
# #
# This source code and the accompanying materials are made available under #
# the terms of the Apache License 2.0 which accompanies this distribution. #
# ============================================================================ #

set(LIBRARY_NAME nvqir-stim)
set(INTERFACE_POSITION_INDEPENDENT_CODE ON)

set(STIM_SOURCE_DIR ${CMAKE_SOURCE_DIR}/tpls/Stim)
set(STIM_BINARY_DIR ${CMAKE_BINARY_DIR}/tpls/Stim)

if(${CMAKE_HOST_SYSTEM_PROCESSOR} STREQUAL "x86_64")
# Constrain to AVX-2 to keep ourselves compatible with x86-64-v3.
set(SIMD_WIDTH 256 CACHE INTERNAL "Pass SIMD width to Stim subproject")
endif()

# The EXCLUDE_FROM_ALL makes it so that only libstim is built. If other targets
# are desired (like the command-line tool), remove EXCLUDE_FROM_ALL below.
add_subdirectory(${STIM_SOURCE_DIR} ${STIM_BINARY_DIR} EXCLUDE_FROM_ALL)

add_library(${LIBRARY_NAME} SHARED StimCircuitSimulator.cpp)
set_property(GLOBAL APPEND PROPERTY CUDAQ_RUNTIME_LIBS ${LIBRARY_NAME})

set (STIM_DEPENDENCIES libstim fmt::fmt-header-only cudaq-common)

# If -Wall is enabled (as is done in parent directories), Stim will not compile.
# So override that here.
target_compile_options(libstim PRIVATE -Wno-all)

target_include_directories(${LIBRARY_NAME}
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/runtime>
$<INSTALL_INTERFACE:include>)

target_link_libraries(${LIBRARY_NAME}
PRIVATE ${STIM_DEPENDENCIES})

set_target_properties(${LIBRARY_NAME}
PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_RPATH}:${LLVM_BINARY_DIR}/lib")

install(TARGETS ${LIBRARY_NAME} DESTINATION lib)

add_target_config(stim)
Loading

0 comments on commit 81c482b

Please sign in to comment.