eigenkit
Build quantum algorithms once. Run them anywhere.
eigenkit is an open-source Python library for quantum computing by
EigenOrbit. It separates the definition of a quantum
algorithm from the backend that executes it. A circuit is described once as
data: the gates, the qubits they act on, and parameters that are constants or
references to trainable weights and data inputs. Each provider compiles that
description into its own SDK's objects and runs it on a simulator or a quantum
processor, so moving an algorithm to another backend means changing the
provider= argument.
Why move between backends
No backend suits every workload, so it is often worth trying several.
Simulators differ in what they are fast at. Which one finishes first depends on the number of qubits, the structure of the circuit and how much entanglement it builds, the batch size, and whether the job evaluates a circuit once or trains a model over many batches. They also differ in which gates and parameter expressions they accept, and in whether they sample shots or run on a GPU.
Quantum processors differ in qubit count, connectivity, native gates, coherence and error rates, as well as in price and queue times. A circuit whose interactions match a device's coupling map needs fewer routing gates there, so the better device can change from one circuit to the next.
eigenkit keeps the algorithm the same on all of them, so trying another backend means changing one argument.
What's in it
- One circuit, many backends. Simulators: the built-in numpy simulator, PennyLane, Qiskit, Qiskit Aer (statevector and matrix-product-state), Qulacs, qsim, TensorCircuit, CUDA-Q and Amazon Braket's simulators. Hardware: IBM through Qiskit Runtime, IQM through IQM Resonance, and the QPUs on Amazon Braket. Photonic circuits run on Quandela's Perceval.
- Gradients on every backend. A provider's own differentiation is used
where it has one: the adjoint method on the built-in simulator, Qulacs and
TensorCircuit, and PennyLane's autodiff. The other simulators and the quantum
hardware get the library's parameter-shift rule through the same interface.
On hardware this is opt-in (
enable_gradients=Truein the device config), since one backward pass runs at least two jobs per weight. - Two ways to build a circuit. Gate by gate with
CircuitBuilder, or from ready-made blocks: encodings, variational layers, data re-uploading. Both produce the same circuit representation. - Fits the classical stack. A circuit is a numpy function or a PyTorch
nn.Module, and the ready-made models follow scikit-learn'sfit/predict. - Algorithms. Machine learning: hybrid neural networks, quantum kernels with QSVC/QSVR, reservoir computing. Optimization: QUBO/Ising, Max-Cut, QAOA. Chemistry: fermionic operators with the Jordan-Wigner and Bravyi-Kitaev mappings, UCCSD, VQE, and molecular Hamiltonians through PySCF and OpenFermion. Also HHL, iterative amplitude estimation (IQAE) and portfolio risk (VaR/CVaR).
- Benchmarking.
compare()runs quantum and classical models on the same data over several seeds;eigenkit.datasetshas loaders and synthetic generators. - A light core. numpy, scipy and pydantic. PyTorch, scikit-learn and every quantum SDK are optional extras, imported on first use.
- Guards on billable hardware. Compiling for a paid device raises a
CostWarning, anddry_run_info()previews a job before it is submitted.
The abstraction adds a few tens of microseconds per call against hand-written code for the same SDK (measured on PennyLane, Qiskit and Qulacs). The expensive native objects, such as a PennyLane QNode or a parametric Qiskit circuit, are built once per circuit and reused on every call.
Installation
eigenkit needs Python 3.12, 3.13 or 3.14.
pip install eigenkit
That alone builds circuits and runs them on the built-in numpy simulator
(provider="numpy", the default), and includes the framework-free
optimization (QAOA) and chemistry (VQE, Jordan-Wigner / Bravyi-Kitaev)
domains. PyTorch, scikit-learn and the quantum-SDK backends are opt-in
extras:
pip install "eigenkit[qiskit,braket]"
pip install "eigenkit[qml]" # torch-free kernel QML (QSVC/QSVR)
pip install "eigenkit[torch]" # differentiable hybrid models (HQNC/HQNR)
pip install "eigenkit[all]"
| Extra | Adds | Unlocks |
|---|---|---|
torch |
PyTorch + scikit-learn (+ tqdm) | interface="torch", the layers, and the hybrid estimators (HQNC/HQNR/...) |
pennylane |
PennyLane + Lightning | provider="pennylane" |
qiskit |
Qiskit + Aer + IBM Runtime | provider="qiskit", "qiskit-aer", "qiskit-aer-mps"; IBM Runtime / QPU |
braket |
Amazon Braket SDK | provider="braket" (local simulator, cloud, AWS QPUs) |
iqm |
iqm-client + its Qiskit adapter | provider="iqm" (IQM Resonance direct, plus IQM's fake backends) |
cudaquantum |
NVIDIA CUDA-Q | CudaQuantumBackend, opt-in (Linux CPU + GPU; macOS Apple Silicon CPU) |
tensorcircuit |
tensorcircuit-ng + JAX | provider="tensorcircuit" |
qulacs |
Qulacs | provider="qulacs" |
qsim |
qsimcirq + Cirq | provider="qsim" (single-precision, ~1e-6 residual) |
perceval |
Perceval (Quandela's photonic SDK) | eigenkit.photonics (local simulation, Quandela Cloud) |
qml |
scikit-learn (torch-free) | QuantumKernel, QSVC/QSVR |
datasets |
scikit-learn | eigenkit.datasets |
benchmark |
matplotlib + pandas + scikit-learn | the model comparison harness |
chemistry |
PySCF + OpenFermion (no PySCF on Windows) | real molecules (molecular_hamiltonian, hydrogen_molecule) |
viz |
matplotlib | Circuit.draw_mpl() (the text drawer needs nothing) |
all |
every extra above except perceval |
— |
A backend class and its config are always importable, but
Circuit(provider="qiskit") (and so on), or a torch-only or sklearn-only
symbol, fails with an install hint until the matching extra is present.
Two backends are opt-in: installing the package does not register a provider name for them, because each needs a deliberate choice from you — CUDA-Q sets a process-global target, and Qiskit Runtime submits billable jobs to real IBM hardware. Register either yourself once, then use the name anywhere:
from eigenkit import CudaQuantumBackend, QiskitRuntimeBackend, register
register("cudaq", CudaQuantumBackend())
register("qiskit-runtime", QiskitRuntimeBackend())
Every other backend registers itself as soon as its package is importable.
CUDA-Q ships wheels for Linux (x86_64 and ARM64) and macOS Apple Silicon; the
latter runs the CPU-only qpp-cpu simulator. On Windows and macOS x86_64 there
are no wheels, so the extra installs nothing there and the backend raises a
clear error if you try to use it.
PySCF does not support Windows, so there the chemistry extra installs
OpenFermion alone, and real molecules need WSL. Linux ARM has a few notes of
its own; the Getting started guide lists them under "Platform compatibility".
Quick start
A Bell pair, built gate by gate and measured on the built-in simulator:
from eigenkit import Circuit, CircuitBuilder, X, Z
qc = CircuitBuilder(n_qubits=2)
qc.h(0).cnot(0, 1)
bell = Circuit(qc.build(), observables=[Z(0) * Z(1), X(0) * X(1)])
print(bell([])) # [1. 1.] - no trainable weights, so an empty weight vector
Running it elsewhere means passing a provider, for example
Circuit(qc.build(), observables=..., provider="qulacs").
A larger circuit follows the same pattern. This IQP circuit (Hadamards, a layer of ZZ rotations, Hadamards) is built by a helper function and run on three simulators:
from eigenkit import Circuit, CircuitBuilder, Z
def iqp(n, edges, angles):
"""H on every qubit, a ZZ rotation per edge, H on every qubit."""
qc = CircuitBuilder(n_qubits=n)
for q in range(n):
qc.h(q)
for (i, j), angle in zip(edges, angles):
qc.pauli_exponential((("Z", i), ("Z", j)), angle)
for q in range(n):
qc.h(q)
return qc.build()
spec = iqp(4, [(0, 1), (1, 2), (2, 3), (3, 0)], [0.7, 1.1, 0.4, 1.9])
observables = [Z(0) * Z(1), Z(1) * Z(2), Z(0) * Z(1) * Z(2) * Z(3)]
for provider in ["numpy", "qulacs", "qiskit-aer"]:
circuit = Circuit(spec, observables=observables, provider=provider)
print(provider, circuit([]))
numpy [0.46548538 0.11841725 1. ]
qulacs [0.46548538 0.11841725 1. ]
qiskit-aer [0.46548538 0.11841725 1. ]
qulacs and qiskit-aer need the qulacs and qiskit extras. On hardware the
provider is a device config, and the rest of the program stays the same. This
needs an IBM Quantum or IQM Resonance account, and compiling for a paid device
warns with a CostWarning first:
from eigenkit import IQMConfig, QiskitRuntimeConfig
devices = {
"IBM Heron": QiskitRuntimeConfig(
backend_name="ibm_kingston", shots=8192, primitive="sampler"
),
"IQM Emerald": IQMConfig(quantum_computer="emerald", shots=8192),
}
for name, device in devices.items():
circuit = Circuit(spec, observables=observables, provider=device)
print(name, circuit([]))
Ready-made blocks cover the common shapes, and jacobian() returns the
gradient with respect to the weights:
import numpy as np
from eigenkit import Circuit, Encoding, Variational, all_z
circuit = Circuit(
blocks=[Encoding(in_features=4), Variational(depth=2)],
observables=all_z(4),
)
weights = np.zeros(circuit.spec.n_weights)
x = np.random.uniform(0, np.pi, size=(8, 4)) # a batch of 8 samples
y = circuit(weights, x) # shape (8, 4): one expectation per qubit
grad = circuit.jacobian(weights, x[0]) # d<O>/d(weights), no torch needed
With interface="torch" (the torch extra) the same circuit is a
torch.nn.Module that owns its weights and trains inside a larger model.
Documentation
The full documentation is at docs.kit.eigenorbit.com:
a user guide per topic, the algorithms explained, worked examples, and the API
reference. Every example page also ships as a notebook in
examples/notebooks/.
Contributing
Bug reports, ideas and pull requests are welcome. CONTRIBUTING.md covers the development setup, tests and conventions, and ARCHITECTURE.md is a tour of the codebase. Please report security issues privately, as described in SECURITY.md.
Citing eigenkit
If eigenkit helps your research, please cite it. GitHub's Cite this repository button gives the reference from CITATION.cff.
License
eigenkit is licensed under the Apache License 2.0.
Metadata
Release files for eigenkit 1.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| eigenkit-1.0.1.tar.gz | 715.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| eigenkit-1.0.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.2 MB
Release files / eigenkit-1.0.1.tar.gz
| Download URL | eigenkit-1.0.1.tar.gz |
|---|---|
| Size | 715.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d51c6e638aedbcefa31a7a59507fec53d55cc465bf170dd4f4c7145fd0a601d5
|
|
BLAKE2b-256 checksum How to use checksums |
d403752abdcdf33f1d59721971736ea91f773ce975767a1d7b241c57f965ccac
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.
Transparency logRelease files / eigenkit-1.0.1-py3-none-any.whl
| Download URL | eigenkit-1.0.1-py3-none-any.whl |
|---|---|
| Size | 481.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
281e93b03fcdd9b720d054dee4f80d66aba954ec3f2a98eacac0143b9777fd43
|
|
BLAKE2b-256 checksum How to use checksums |
30b37db83ead978bceb8a9e47eb1c2a3ab20fb0754ddd18fabb5e95d4885b501
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.
Transparency log