# qsim: a full state-vector simulator for quantum circuits

> qsim is the C++ and Python state-vector simulator from Google Quantum AI, exposing a Cirq interface and a header library that fuses gates for speed. It computes every amplitude of the state, so the qubit count sets the ceiling on what you can simulate.

**quantumlib/qsim** — Fast C++ and Python library for state-vector simulation of quantum circuits.

- Repository: https://github.com/quantumlib/qsim
- Website: https://quantumai.google/qsim
- Stars: 709 · Forks: 224
- Language: C++
- License: Apache-2.0
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/quantumlib-qsim

## Every amplitude is computed, so the qubit count sets the ceiling

qsim is a state-vector simulator for quantum circuits, also called a Schrodinger simulator. The README describes the mechanism plainly: it represents a quantum state as a vector of complex-valued amplitudes and applies matrix-vector multiplication to simulate the transformations that evolve the state over time.

The word full in that description is the whole story. qsim computes all the 2 to the power n amplitudes of the state vector, where n is the number of qubits, and the total runtime is proportional to g times 2 to the power n, where g is the number of two-qubit gates. Every amplitude means every one of them is stored, so memory scales the same way the work does.

That is a deliberate trade rather than a gap. A full state vector gives you exact amplitudes for the entire wavefunction, which is what you want when the task is to sample from the distribution, to compute an expectation value, or to check a circuit against a reference. It also means the tool is the wrong one for circuits where the state stays small because of structure, since a Clifford-heavy circuit or a circuit with a low bond dimension can be simulated far past the qubit count a dense state vector could reach. The README does not document noise models, error mitigation or approximation methods, so those workloads are not in scope here.

The project is hosted under the quantumlib organisation, the homepage is quantumai.google/qsim, and the licence is Apache 2.0 with the copyright held by Google LLC.

## Gate fusion and single precision do the heavy lifting

The speed of a state-vector simulator comes from two things: doing fewer matrix-vector products, and doing each one faster. qsim addresses both, and the README is explicit about the ingredients.

The first is gate fusion, cited to Smelyanskiy et al. from 2016 and Haener and Steiger from 2017. Fusion merges adjacent single-qubit gates on the same qubit into a single operation before the matrix-vector product runs, which removes a large number of round trips through the state vector. The second is single-precision arithmetic for the amplitudes, which halves the memory traffic compared with double precision.

On top of that sit the hardware paths: AVX and FMA instructions for vectorization, and OpenMP for multithreading, both applied where the hardware provides them. The README also says qsim is tuned to take advantage of vector arithmetic instruction sets and multithreading, and GPUs when they are available.

Two observations follow for an adopter. The scaling formula ties cost to the number of two-qubit gates rather than to the total gate count, so a circuit padded with single-qubit gates is relatively cheap. And the vectorization and threading benefits are conditional on the machine, which means the same circuit can behave very differently across a laptop and a server, and a benchmark taken on one is not evidence about the other.

## The C++ core is a library you include, not a service

The code is designed to be included in users' applications rather than run as a daemon. The README points to the sample applications in the apps directory as starting points, and notes that the core qsim library, located in the source repository under the lib subdirectory, can be included directly in C++ programs without installing the Python interface at all.

That split has consequences for how you integrate it. There is no server to deploy and no wire protocol to design around; the simulator becomes part of your binary and its performance characteristics become your program's performance characteristics. For a team with an existing C++ codebase, that is usually the cheapest possible adoption path. For a team working in Python, the same core is reached through the pybind_interface directory and the qsimcirq package.

The repository carries both build systems you would expect from a Google project of this size, with a CMakeLists.txt at the top level and Bazel configuration through WORKSPACE, .bazelrc and .bazelversion. A Dockerfile, a docker-compose.yml and a Makefile sit alongside them, and the top level also holds circuits/, check/, dev_tools/, install/ and jupyter/ directories. The jupyter directory is worth noting for teaching and for quick experiments, since the Python interface is what a notebook user touches.

## qsimcirq plugs the engine into Cirq

For Python users, the entry point is qsimcirq, the qsim-Cirq Python interface. The README states it is available as a PyPI package for Linux, MacOS and Windows users, and that it can be installed with a single command.

```shell
pip install qsimcirq
```

Because wheels exist for the three desktop platforms, the usual path does not involve a compiler on the reader's machine. That is a meaningful difference from building the C++ core by hand.

The integration is with Cirq, the framework for modeling and invoking Noisy Intermediate-Scale Quantum circuits, and the README says qsim includes a Cirq interface and can be used to simulate circuits written in Cirq. It points to a tutorial notebook for getting started with simulating Cirq circuits using qsim, and to separate documentation for the qsim-Cirq API.

The dependency picture is modest. The requirements file lists absl-py and cirq-core at roughly the 1.0 line as the core dependencies, with numpy and scipy pinned differently depending on the Python version: numpy below 2.0.0 and scipy below 1.15.0 for Python 3.10, and numpy 1.26.0 or newer for anything above it. The stated reason is that some versions dropped support for Python 3.10, and contourpy is constrained for the same reason since it is pulled in by Matplotlib, which is pulled in by Cirq. So a Python 3.10 environment is a slightly more constrained one, not an unsupported one.

## Building from source checks your CMake version first

The source build path is documented more carefully than most, and it fails fast on the one thing that is easy to get wrong. setup.py runs cmake --version, parses the reported version and compares it against 3.28.0, raising a RuntimeError if the installed CMake is older. The pyproject.toml build requirements agree, asking for cmake at roughly 3.28.1 alongside pybind11, setuptools-scm, setuptools and wheel.

The Python floor is 3.10, stated in the README badge and consistent with the version-specific pins in the requirements file. The package metadata also names the distribution qsimcirq, while the underlying C++ library keeps the qsim name.

Two details deserve attention from an adopter. setup.py reads the version from qsim/_version.py through runpy and asserts that the version string is not empty, which means the version lives in a generated file inside the package rather than being hand-maintained in one place. And the version string is what the Zenodo citation workflow depends on, since the README asks that published work cite the qsim version used so results can be reproduced.

For most users none of this matters, because the PyPI wheel already contains the compiled engine. It matters to teams building from source for a custom CPU target, for a GPU path, or for an internal platform where a pinned wheel is not acceptable.

## Docker Compose separates the three build targets

The repository includes a docker-compose.yml that defines three services, and the split is more informative than it first appears. The first, qsim-base-image, builds from the top level Dockerfile with the target qsim-base, on platform linux/amd64. The second, qsim-cxx-tests-image, builds from tests/Dockerfile with the target qsim-cxx-tests and declares a dependency on the base image. The third, qsim-py-tests-image, builds from pybind_interface/Dockerfile with the target qsim-py-tests and depends on the same base.

So the C++ test suite and the Python test suite are built in separate images on top of a shared base, rather than sharing one environment. That mirrors the split in the source tree, where C++ tests live in tests and Python tests live in qsimcirq_tests, and it keeps a toolchain problem in one half from masking a failure in the other.

The C++ side uses GoogleTest, and the README points to the tests directory for the framework and the layout. The Python side uses pytest, with tests in qsimcirq_tests. Both are named in the documentation alongside the make targets that run them, so a contributor can reproduce the same split locally.

The presence of a hadolint configuration and a .dockerignore at the top level suggests the images are linted in CI, and the repository also carries a .github directory, a CODE_OF_CONDUCT.md, a CONTRIBUTING.md and a SUPPORT.md. For an adopter, the practical value is reproducibility: the container route gives the same toolchain on every machine that builds the images, which matters most for the platform-specific paths the simulator takes.

## make run-tests compiles and runs everything in series

The test entry point is a single make target, and the README describes exactly what it does.

```shell
make run-tests
```

It compiles all the test binaries to files with .x extensions and runs each test in series, stopping early if a test fails. It also runs the tests of the qsimcirq Python interface. When you only want part of that, the README gives make run-cxx-tests for the C++ tests and make run-py-tests for the Python tests, and make clean from the test directory to remove the generated files.

Running in series is a deliberate choice for a suite that compiles binaries before running them, and it is the honest way to run tests on a machine with limited cores, since the same libraries compete for the same OpenMP threads when they run in parallel.

The unit tests themselves are straightforward. C++ tests use GoogleTest and live in the tests directory, Python tests use pytest and live in qsimcirq_tests. Beyond the code, the repository carries a CITATION.cff file, a Zenodo archive of releases, and the README's request to cite the specific version you used when publishing results. It also states that the project is not an officially supported Google product and is not eligible for the Google Open Source Software Vulnerability Rewards Program, and gives quantum-oss-maintainers@google.com as the contact for questions. Maintenance is current: the last push was on 2026-10-20, and the release list shows v0.22.1 on 2026-09-01 after v0.22.0 in June 2025 and v0.21.0 in February 2024.

## Conclusion

qsim fits a research or teaching team that needs fast exact simulation of circuits with a modest number of qubits, and it does not fit a workload that needs noise models, error mitigation or circuits whose qubit count is large. Before adopting it, install qsimcirq and run make run-tests to confirm the build and the Python interface work on your machine, then check the memory ceiling of a full state vector against your largest circuit.

## FAQ

### How do I install the Python interface to qsim?

Install the qsimcirq package with pip install qsimcirq, which is available for Linux, MacOS and Windows. The underlying C++ library can also be included directly in C++ programs from the lib subdirectory without the Python interface.

### What does qsim compute and how does the cost scale?

qsim is a full state-vector simulator, so it computes all 2 to the power n amplitudes of the state for n qubits. The README states that total runtime is proportional to g times 2 to the power n, where g is the number of two-qubit gates.

### How do I run the qsim test suite?

Run make run-tests to compile all C++ test binaries with .x extensions and run them in series, along with the qsimcirq Python tests. Use make run-cxx-tests or make run-py-tests to run only one side, and make clean from the test directory to remove generated files.

### What does it take to build qsim from source?

The build uses setuptools with a CMake extension, and setup.py checks the CMake version and refuses to continue below 3.28.0, with pyproject.toml requiring cmake around 3.28.1. Python 3.10 or newer is required, and the C++ tests use GoogleTest while the Python tests use pytest.

### Can I use qsim with Cirq?

Yes. The qsimcirq package is the Cirq interface, and the README says qsim can be used to simulate quantum circuits written in Cirq, with a tutorial notebook and separate API documentation provided.

## Sources

- [License: Apache-2.0](https://github.com/quantumlib/qsim/blob/main/LICENSE)
- [Project website](https://quantumai.google/qsim)
- [quantumlib/qsim on GitHub](https://github.com/quantumlib/qsim)
- [README](https://github.com/quantumlib/qsim/blob/main/README.md)
- [Releases](https://github.com/quantumlib/qsim/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/quantumlib-qsim
