Metadata-Version: 2.4
Name: scaluq
Version: 0.2.0
Summary: Quantum circuit simulator for research
Author-Email: Qulacs-Osaka <qulacs.osaka@gmail.com>
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX
Classifier: Programming Language :: Python
Classifier: Topic :: Communications :: Email
Project-URL: homepage, http://www.scaluq.org
Requires-Python: >=3.10
Requires-Dist: numpy>=1.22.0
Requires-Dist: scipy>=1.11.0
Provides-Extra: doc
Requires-Dist: black==26.3.1; extra == "doc"
Requires-Dist: isort==5.13.2; extra == "doc"
Requires-Dist: myst_parser==4.0.1; extra == "doc"
Requires-Dist: nanobind==2.0.0; extra == "doc"
Requires-Dist: astroid==3.3.11; extra == "doc"
Requires-Dist: sphinx==7.3.7; extra == "doc"
Requires-Dist: sphinx-autoapi==3.1.1; extra == "doc"
Requires-Dist: sphinxcontrib-napoleon==0.7; extra == "doc"
Requires-Dist: sphinx_rtd_theme==2.0.0; extra == "doc"
Requires-Dist: sphinx-math-dollar==1.2.1; extra == "doc"
Description-Content-Type: text/markdown

# Scaluq

![](https://app.readthedocs.org/projects/scaluq/badge/)
[![Build and Test](https://github.com/qulacs/scaluq/actions/workflows/test_all.yml/badge.svg)](https://github.com/qulacs/scaluq/actions/workflows/test_all.yml)
[![Format](https://github.com/qulacs/scaluq/actions/workflows/format.yml/badge.svg)](https://github.com/qulacs/scaluq/actions/workflows/format.yml)
[![Install to System](https://github.com/qulacs/scaluq/actions/workflows/install_merge.yml/badge.svg)](https://github.com/qulacs/scaluq/actions/workflows/install_merge.yml)
[![Sdist build](https://github.com/qulacs/scaluq/actions/workflows/sdist.yml/badge.svg)](https://github.com/qulacs/scaluq/actions/workflows/sdist.yml)
[![Wheel build](https://github.com/qulacs/scaluq/actions/workflows/wheel_merge.yml/badge.svg)](https://github.com/qulacs/scaluq/actions/workflows/wheel_merge.yml)

**For the Japanese version of this README, see [README_ja.md](README_ja.md).**

Scaluq is a newly redeveloped Python/C++ library based on the quantum circuit simulator [Qulacs](https://github.com/qulacs/qulacs).  
It enables high-speed simulation of large-scale quantum circuits, noisy quantum circuits, and parametric quantum circuits.  
This library is released under the MIT License.

Compared to [Qulacs](https://github.com/qulacs/qulacs), the following improvements have been made:

- Implementation based on [Kokkos](https://github.com/kokkos/kokkos) allows seamless switching between execution environments (CPU/GPU) without requiring code changes.
- Provides execution speeds comparable to Qulacs on CPU, and achieves equivalent or faster speeds on GPU.
- Pointers are hidden from users, making the code simpler and safer to write.
- Integration of [nanobind](https://github.com/wjakob/nanobind) enables lightweight and low-overhead Python bindings.
- Provides batched execution for efficiently applying quantum circuits with the same structure but different parameters to multiple quantum states.

# Documentation

See https://scaluq.readthedocs.io/en/latest/index.html

# Performance

The execution times of our quantum circuit simulator and several existing quantum circuit simulators were compared.  
In this benchmark, a circuit consisting of CX, RX, and RZ gates applied sequentially to different target qubits was executed, and the average execution time was measured.

See [the benchmark repository](https://github.com/Qulacs-Osaka/benchmark-scaluq).

## CPU: Single State Vector Update (June 2026)

| CPU single thread | CPU multi thread |
| ----------------- | ---------------- |
| ![Single State Vector Update (CPU single thread)](https://github.com/Qulacs-Osaka/benchmark-scaluq/raw/main/benchmark/multiple-gate/multithread/image/circuit_singlethread.png) | ![Single State Vector Update (CPU multi thread)](https://github.com/Qulacs-Osaka/benchmark-scaluq/raw/main/benchmark/multiple-gate/multithread/image/circuit_multithread.png) |

## GPU: Single State Vector Update (August 2026)

| GPU |
| :--- |
| <img src="https://github.com/Qulacs-Osaka/benchmark-scaluq/raw/main/benchmark/multiple-gate/gpu/image/circuit_gpu.png" width="50%"> |

## Batched State Vector Update (June 2026)

| Varying batch size (#qubits=16) | Varying #qubits (batch size=100) |
| ------------------------------- | -------------------------------- |
| ![Batched State Vector Update (batch sweep)](https://github.com/Qulacs-Osaka/benchmark-scaluq/raw/main/benchmark/batch/image/batch_sweep.png) | ![Batched State Vector Update (qubits sweep)](https://github.com/Qulacs-Osaka/benchmark-scaluq/raw/main/benchmark/batch/image/qubits_sweep.png) | 

## Build Requirements

- Ninja ≥ 1.10
- GCC ≥ 13 or LLVM Clang ≥ 18
  - if you enable CUDA, GCC ≥ 11 is OK, but you cannot use Clang.
- CMake ≥ 3.24
- CUDA ≥ 12.8 (only when using CUDA)
- Python ≥ 3.10 (only when using Python)

When using CUDA, use a host compiler version supported by your CUDA toolkit (see the CUDA Installation Guide Host Compiler Support Policy).

Note: It may work with lower versions, but this has not been verified.

## Runtime Requirements

- CUDA ≥ 12.8 (only when using CUDA)

Note: It may work with lower versions, but this has not been verified.

## Build Options

Build options can be specified using environment variables when running `script/configure` or `pip install .`.

| Variable Name           | Default     | Description |
|------------------------|-------------|-------------|
| `CMAKE_C_COMPILER`     | -           | See [CMake Documentation](https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_COMPILER.html) |
| `CMAKE_CXX_COMPILER`   | -           | See [CMake Documentation](https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_COMPILER.html) |
| `CMAKE_BUILD_TYPE`     | -           | See [CMake Documentation](https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html) |
| `CMAKE_INSTALL_PREFIX` | -           | See [CMake Documentation](https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX.html) |
| `SCALUQ_USE_OMP`       | `ON`        | Use OpenMP for parallel computation on CPU |
| `SCALUQ_USE_CUDA`      | `OFF`       | Enable parallel computation using GPU (CUDA) |
| `SCALUQ_CPU_NATIVE`    | `ON`        | Build for native CPU architecture of builder's |
| `SCALUQ_CPU_ARCH`      | -           | Target CPU architecture (see [Kokkos CMake Keywords](https://kokkos.org/kokkos-core-wiki/get-started/configuration-guide.html), e.g., `SCALUQ_CPU_ARCH=SKX`) |
| `SCALUQ_CUDA_ARCH`     | (auto)      | Target Nvidia GPU architecture (see [Kokkos CMake Keywords](https://kokkos.org/kokkos-core-wiki/get-started/configuration-guide.html), e.g., `SCALUQ_CUDA_ARCH=AMPERE80`) |
| `SCALUQ_USE_TEST`      | `OFF`        | Include `test/` in build targets. You can build and run tests with `ctest --test-dir build/` |
| `SCALUQ_USE_EXE`       | `OFF`        | Include `exe/` in build targets. You can try running without installing by building with `ninja -C build` and running `build/exe/main` |
| `SCALUQ_FLOAT16`       | `OFF`       | Enable `f16` precision |
| `SCALUQ_FLOAT32`       | `ON`        | Enable `f32` precision |
| `SCALUQ_FLOAT64`       | `ON`        | Enable `f64` precision |
| `SCALUQ_BFLOAT16`      | `OFF`       | Enable `bf16` precision |

## Installing as a C++ Library

To install Scaluq as a static C++ library, run the following commands:

```txt
git clone https://github.com/qulacs/scaluq
cd scaluq
script/configure
sudo -E env "PATH=$PATH" ninja -C build install
```

- Required libraries such as Eigen and Kokkos will be installed together.
- You can install to a location other than `/usr/local/` by setting `CMAKE_INSTALL_PREFIX`. For example, if you want to install locally or avoid conflicts with other Kokkos builds:  
  `CMAKE_INSTALL_PREFIX=~/.local script/configure; ninja -C build install`
- `sudo` is used to install files to `/usr/local/`, but to preserve the user environment, we use `-E` and explicitly pass `PATH`.
- If you want to build the CUDA-enabled version (when NVIDIA GPU and CUDA are available), set `SCALUQ_USE_CUDA=ON`. Example:  
  `SCALUQ_USE_CUDA=ON script/configure; sudo env -E "PATH=$PATH" ninja -C build install`

When changing options and rebuilding, make sure to clear the CMake cache by running:

```txt
rm build/CMakeCache.txt
```

An example CMake configuration for a project using the installed Scaluq library is provided in [example_project/](example_project/CMakeLists.txt).

## Installing as a Python Library

Scaluq can also be used as a Python library:

```txt
pip install scaluq
```

If you want to use GPU or precisions other than `f32` and `f64`, clone the repository and install with options:

```txt
git clone https://github.com/qulacs/scaluq
cd ./scaluq
SCALUQ_USE_CUDA=ON pip install .
```

## Python Documentation

A simple documentation page is available with function descriptions and type information for the Python library version:  
https://scaluq.readthedocs.io/en/latest/index.html

## Sample Code (C++)

```cpp
#include <cstdint>
#include <iostream>
#include <scaluq/circuit/circuit.hpp>
#include <scaluq/gate/gate_factory.hpp>
#include <scaluq/operator/operator.hpp>
#include <scaluq/state/state_vector.hpp>

int main() {
    scaluq::initialize();  // must be called before using any scaluq methods
    {
        constexpr scaluq::Precision Prec = scaluq::Precision::F64;
        constexpr scaluq::ExecutionSpace Space = scaluq::ExecutionSpace::Default;
        const std::uint64_t n_qubits = 3;
        scaluq::StateVector<Prec, Space> state =
            scaluq::StateVector<Prec, Space>::Haar_random_state(n_qubits, 0);
        std::cout << state << std::endl;

        scaluq::Circuit<Prec> circuit;
        circuit.add_gate(scaluq::gate::X<Prec>(0));
        circuit.add_gate(scaluq::gate::CNot<Prec>(0, 1));
        circuit.add_gate(scaluq::gate::Y<Prec>(1));
        circuit.add_gate(scaluq::gate::RX<Prec>(1, std::numbers::pi / 2));
        circuit.update_quantum_state(state);

        std::vector<scaluq::PauliOperator<Prec>> terms;
        terms.emplace_back(1, 0);
        scaluq::Operator<Prec, Space> observable(terms);
        auto value = observable.get_expectation_value(state);
        std::cout << value << std::endl;
    }
    scaluq::finalize();  // must be called last
}
```

By including `scaluq/all.hpp`, you can omit template arguments using `SCALUQ_OMIT_TEMPLATE`.

```cpp
#include <cstdint>
#include <iostream>
#include <scaluq/all.hpp>

namespace my_scaluq {
SCALUQ_OMIT_TEMPLATE(scaluq::Precision::F64, scaluq::ExecutionSpace::Default)
}

using namespace my_scaluq;

int main() {
    scaluq::initialize();  // must be called before using any scaluq methods
    {
        const std::uint64_t n_qubits = 3;
        StateVector state = StateVector::Haar_random_state(n_qubits, 0);
        std::cout << state << std::endl;

        Circuit circuit;
        circuit.add_gate(gate::X(0));
        circuit.add_gate(gate::CNot(0, 1));
        circuit.add_gate(gate::Y(1));
        circuit.add_gate(gate::RX(1, std::numbers::pi / 2));
        circuit.update_quantum_state(state);

        std::vector<PauliOperator> terms;
        terms.emplace_back(1, 0);
        Operator observable(terms);
        auto value = observable.get_expectation_value(state);
        std::cout << value << std::endl;
    }
    scaluq::finalize();  // must be called last
}
```

## Sample Code (Python)

```python
from scaluq import StateVector, Circuit, PauliOperator, Operator
from scaluq import gate
import math

n_qubits = 3
state = StateVector.Haar_random_state(n_qubits, 0)

circuit = Circuit()
circuit.add_gate(gate.X(0))
circuit.add_gate(gate.CNot(0, 1))
circuit.add_gate(gate.Y(1))
circuit.add_gate(gate.RX(1, math.pi / 2))
circuit.update_quantum_state(state)

terms = [PauliOperator("Z 0")]
observable = Operator(terms)
value = observable.get_expectation_value(state)
print(value)
```

# Specifying Precision and Execution Space

Scaluq supports multiple floating-point precisions: `f16`, `f32`, `f64`, and `bf16`.  
By default, only `f32` and `f64` are enabled.  
While `f64` is generally recommended, lower precisions like `f32` can be up to 2–4x faster in applications such as quantum machine learning that do not require high precision.

| Precision | C++ Template Argument         | Python keyword (`precision=`) | Description               |
|-----------|-------------------------------|-------------------------------|---------------------------|
| `f16`     | `Precision::F16`              | `'f16'`                       | IEEE754 binary16          |
| `f32`     | `Precision::F32`              | `'f32'`                       | IEEE754 binary32          |
| `f64`     | `Precision::F64`              | `'f64'`                       | IEEE754 binary64          |
| `bf16`    | `Precision::BF16`             | `'bf16'`                      | bfloat16                  |

Note: With `f16` / `bf16` precision, the calculation error may be very large (sometimes larger than $0.1$). We do not test the accuracy with these options.

Execution spaces determine whether computation is performed on CPU or GPU:

| Execution Space  | C++ Template Argument        | Python keyword (`space=`)  | Description                                   |
|------------------|------------------------------|----------------------------|-----------------------------------------------|
| `default`        | `ExecutionSpace::Default`    | `'default'`                | Runs on GPU if CUDA is enabled, otherwise CPU |
| `host`           | `ExecutionSpace::Host`       | `'host'`                   | Always runs on CPU                            |
| `host_serial`    | `ExecutionSpace::HostSerial` | `'host_serial'`            | Always runs sequentially on CPU               |

Note: You can only perform operations between objects with the same precision and execution space. For example, a gate created for 32-bit precision cannot be used with a 64-bit StateVector, even if both are CPU-based.

In C++, classes like StateVector, Circuit, Gate, and Operator accept `Precision` and `ExecutionSpace` as template arguments.

In Python, top-level classes such as `StateVector` and `Circuit`, as well as gate factories in `scaluq.gate`, accept `precision` and `space` keyword arguments, defaulting to `'f64'` and `'default'` respectively.

```python
from scaluq import StateVector, Circuit
from scaluq import gate

prec = 'f64'
space = 'default'

state = StateVector(3, precision=prec, space=space)
x = gate.X(0, precision=prec)
x.update_quantum_state(state)
print(state)
```
