https://github.com/osamamit/qitesse
Python API for performant quantum circuit simulation using qitesse-sim
https://github.com/osamamit/qitesse
Last synced: 2 months ago
JSON representation
Python API for performant quantum circuit simulation using qitesse-sim
- Host: GitHub
- URL: https://github.com/osamamit/qitesse
- Owner: OsamaMIT
- License: mit
- Created: 2025-09-22T15:41:39.000Z (9 months ago)
- Default Branch: main
- Last Pushed: 2026-04-06T06:42:17.000Z (2 months ago)
- Last Synced: 2026-04-06T08:44:38.329Z (2 months ago)
- Language: Rust
- Homepage:
- Size: 90.8 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# qitesse
[](https://pypi.org/project/qitesse/)
[](https://github.com/OsamaMIT/qitesse/blob/main/LICENSE)
[](https://pypi.org/project/qitesse/)
**qitesse** is a high-throughput CPU backend for repeated evaluation of parameterized quantum circuits.
qitesse is built upon qitesse-sim, the **high-performance CPU-based state-vector execution engine** for quantum circuits, fully built in Rust.
This PyPI module provides a Python interface designed for hybrid quantum algorithms, repeated circuit evaluation, backend integration, and low-overhead CPU execution from Python.
## Features
- Rust-based CPU statevector simulator with a Python API
- One-off circuit execution through `Gate` and `Circuit`
- Compiled parameterized circuits through `CircuitSpec`, `Parameter`, and `CompiledCircuit`
- Reusable zero-copy parameter buffers through `ParamBuffer` and `ParamBatchBuffer`
- Expectation-value workflows for Pauli observables and Hamiltonians
- Batch expectation execution for parameter sweeps and optimizer loops
- Gradient APIs for compiled circuits via parameter-shift evaluation
- Reusable `ExecutionContext` buffers for repeated scalar execution
- Full statevector output for both one-off and compiled execution paths
- Mid-circuit `measure`, `reset`, and `barrier` operations
- Custom unitary operations with `Gate.unitary(...)`
- Controlled custom unitaries with `Gate.controlled_unitary(...)`
- Common single-, two-, and multi-qubit gates
- Read the Docs documentation with autogenerated API reference pages
## Installation
qitesse requires **Python 3.8+**. Install it via pip:
```bash
pip install qitesse
```
Or install from source:
```bash
git clone https://github.com/OsamaMIT/qitesse.git
pip install maturin
maturin develop --release
```
To run examples:
`python examples/h_example.py`
`python examples/qft._example.py`
`python examples/custom_unitary.py`
## Documentation
The documentation is now set up for Read the Docs with automatic API generation.
- Entry point: [docs/index.rst](docs/index.rst)
- Current features: [docs/current_features.rst](docs/current_features.rst)
- Compiled execution guide: [docs/guides/compiled_execution.rst](docs/guides/compiled_execution.rst)
- Generated API reference root: [docs/api/index.rst](docs/api/index.rst)
- Read the Docs config: [.readthedocs.yaml](.readthedocs.yaml)
To add a new public class to the API docs, add it once in [docs/api/index.rst](docs/api/index.rst). Sphinx will generate the class page and include its methods and attributes automatically.
## Current Capabilities
qitesse currently has two main usage modes:
1. General-purpose simulation with `Gate` and `Circuit` for one-off execution.
2. Compiled execution with `CircuitSpec` and `CompiledCircuit` for repeated parameterized workloads.
The compiled path currently supports:
- reusable zero-copy parameter buffers
- scalar expectation evaluation
- batched expectation evaluation
- scalar gradients
- batched gradients
- reusable execution contexts
- statevector inspection when needed
The simulator path currently supports:
- standard single-qubit gates
- controlled and multi-qubit gates
- custom unitaries
- measurement, reset, and barrier operations
## Compiled Circuits
```python
import numpy as np
import qitesse
spec = qitesse.CircuitSpec(2)
theta = spec.param("theta")
spec.ry(0, theta)
spec.cx(0, 1)
compiled = spec.compile()
observable = qitesse.Observable.pauli_z(1)
value = compiled.expectation(np.array([0.4], dtype=np.float32), observable)
gradient = compiled.gradient(np.array([0.4], dtype=np.float32), observable)
value_again, grad_again = compiled.value_and_gradient(
np.array([0.4], dtype=np.float32),
observable,
)
state = compiled.statevector(np.array([0.4], dtype=np.float32))
params_batch = np.array([[0.1], [0.2], [0.3]], dtype=np.float32)
values = compiled.batch_expectation(params_batch, observable)
grads = compiled.batch_gradient(params_batch, observable)
context = compiled.execution_context()
value_again = context.expectation(compiled, np.array([0.5], dtype=np.float32), observable)
grad_again = context.gradient(compiled, np.array([0.5], dtype=np.float32), observable)
```
This execution path is intended for repeated evaluation of the same circuit structure with different parameter values.
## Backend Integration
The compiled execution path is the primary integration surface for higher-level libraries.
The intended backend pattern is:
1. Translate a framework circuit into `CircuitSpec`
2. Compile once per circuit structure
3. Keep parameters in contiguous `numpy.float32` arrays
4. Call `expectation`, `batch_expectation`, `gradient`, or `value_and_gradient`
For sequential scalar calls, reuse `compiled.execution_context()` to keep internal buffers alive.
For sweeps, minibatches, or optimizer batches, prefer `batch_expectation(...)` and `batch_gradient(...)` instead of looping in Python.
## Supported Gates
Single-qubit gates:
- `i`
- `x`
- `y`
- `z`
- `h`
- `s`
- `sdg`
- `t`
- `tdg`
- `rx`
- `ry`
- `rz`
- `p` / `phase`
- `u`
Two-qubit gates:
- `cnot` / `cx`
- `cy`
- `cz`
- `ch`
- `swap`
- `iswap`
- `crx`
- `cry`
- `crz`
- `cp` / `cphase`
- `cu`
Three-qubit and larger:
- `ccx` / `toffoli`
- `cswap` / `fredkin`
- `mcx`
- `mcz`
- `mcp` / `mcphase`
- `controlled_unitary`
Circuit operations:
- `measure`
- `reset`
- `barrier`
Custom unitaries:
```python
import numpy as np
import qitesse
hadamard = np.array([[1, 1], [1, -1]], dtype=np.complex64) / np.sqrt(2)
circuit = qitesse.Circuit([
qitesse.Gate.unitary([0], hadamard),
qitesse.Gate.controlled_unitary([0], [1], hadamard),
])
state = circuit.run(2)
```
Use `run_with_measurements(num_qubits)` if the circuit contains measurement gates and you want the observed bit values back.
## Planned Features
- Additional simulation backends
## Contributing
Contributions are welcome! To contribute:
1. Fork the repository
2. Create a new branch (feature-branch)
3. Commit your changes and open a pull request
## License
This project is licensed under the MIT License. See the LICENSE file for details.