Skip to main content

qiskit-zksf

CI PyPI Python Qiskit License: MIT DOI Qiskit Ecosystem

Qiskit provider for ZKSF (Zero Kelvin Simulation Foundry). Point circuits you have already written at classical simulators, GPU accelerators, or real quantum processors, and get a documented accuracy statement back with every approximate result.

pip install qiskit-zksf
from qiskit import QuantumCircuit
from qiskit_zksf import ZKSFProvider

qc = QuantumCircuit(40, 40)
qc.h(0)
for i in range(39):
    qc.cx(i, i + 1)
qc.measure(range(40), range(40))

backend = ZKSFProvider(token="...").backend("zksf_auto")
job = backend.run(qc, shots=1000)

print(job.result().get_counts())
print(job.error_info())     # how far that answer may be from the truth

The token comes from the console at app.zksf.org, or from the ZKSF_TOKEN environment variable.

V2 primitives

Current Qiskit code builds a primitive rather than calling backend.run(), so both are provided. They follow Qiskit's own semantics: one result per PUB, with parameter bindings carried in the array shape.

from qiskit_zksf import ZKSFProvider

provider = ZKSFProvider()

# Sampler: outcome distributions
sampler = provider.sampler()
result = sampler.run([qc], shots=1000).result()
result[0].data.meas.get_counts()
result[0].metadata["error_info"]        # the accuracy statement

# Estimator: expectation values
from qiskit.quantum_info import SparsePauliOp

estimator = provider.estimator()
result = estimator.run([(circuit, SparsePauliOp("ZZ"))]).result()
result[0].data.evs                       # the value
result[0].data.stds                      # the bound on it, not a guess

stds is not invented. Where the engine reports a measured bound it is passed through unchanged, so an EstimatorV2 standard error means the same thing the protocol means.

provider.estimator() defaults to the Pauli propagation engine, which answers with an expectation value directly and bounds it by the discarded coefficient mass.

Parameter sweeps cost money

A local primitive will evaluate a thousand parameter bindings without comment. Here every binding is a separate billed job, because the service has no batch endpoint yet, so a sweep is refused rather than silently charged:

sampler.run([(circuit, thousand_angles)])
# TooManyJobs: this run would submit 1000 separate billed jobs ...

Raise the limit deliberately when that is what you want:

provider.sampler(max_jobs_per_run=200)

Combining an observable array with a parameter sweep in one PUB is not supported. It raises rather than guessing a broadcast order, since guessing would mislabel every value returned.

Why this exists

Exact statevector simulation stops near 30 to 32 qubits, because state size grows as 2^n. Past that, every practical method is approximate: tensor networks truncate the bond dimension, Pauli propagation truncates operator weight, real hardware substitutes device noise for the ideal distribution.

Simulators do not normally tell you how much of the answer that cost you, even though the error quantities exist inside the simulation. job.error_info() is that number.

{'protocol': 'ZCC-v0.1',
 'method': 'MPS (quimb), measured discarded-weight bound',
 'truncation_weight': 2.220446049250313e-16,
 'error_bound': 2.1073424255447017e-08,
 'certified': True,
 'converged': True}

Any finished job can be minted into a public certificate that anyone can check without an account, using zcc-verify. The protocols are specified in a citable paper: doi.org/10.5281/zenodo.21851381.

Backends

Backend Engine Qubits Notes
zksf_auto router picks 128 Default. Chooses the cheapest adequate engine
zksf_exact_cpu exact.cpu 30 Exact statevector
zksf_exact_gpu exact.gpu 32 Exact statevector on GPU, size-routed across two tiers
zksf_mps mps.quimb.cpu 128 Tensor network, supports certified=True
zksf_mps_aer mps.aer.cpu 128 Tensor network (Aer)
zksf_clifford clifford 5000 Stabilizer, exact for Clifford circuits
zksf_pauli pauli.cpu 1024 Heisenberg picture, needs an observable
zksf_noisy noisy.cpu 30 Device noise model, supports mitigate=True
zksf_rigetti qpu.rigetti 108 Rigetti Cepheus-1-108Q superconducting, real hardware
zksf_ionq qpu.ionq 36 IonQ Forte Enterprise 1, real hardware
zksf_iqm_emerald qpu.iqm.emerald 54 IQM Emerald superconducting, real hardware
zksf_iqm_garnet qpu.iqm.garnet 20 IQM Garnet superconducting, real hardware
zksf_aqt_ibex qpu.aqt.ibex 12 AQT IBEX Q1 trapped-ion, real hardware
provider = ZKSFProvider()
provider.backends()                      # all of them
provider.backends(min_num_qubits=100)    # only the ones that reach 100 qubits
provider.backends(hardware=True)         # only real quantum processors

Qubit counts mirror the limits the service enforces, so a circuit too large for an engine fails at transpile time instead of after a round trip. The stabilizer backend advertises only Clifford gates, so the transpiler will not hand it a T gate that Stim cannot represent.

Estimate before you spend

Qiskit has no equivalent concept, so this lives on the provider. It is free, instant, and the only way to learn that a circuit would be rejected without submitting it.

est = provider.estimate(qc, shots=1000)
print(est["engine"], est["predicted_cost_usd"], est["reason"])

Asking for a measured bound

By default an approximate run is checked by convergence: the circuit is simulated again at double the resource budget and the shift in outcome probabilities is reported. That is evidence of accuracy, not a bound.

certified=True asks the tensor-network engine for a stronger statement. It runs with state renormalization disabled, so the final state's norm deficit equals the total weight discarded across every truncation, read directly off the result rather than estimated.

job = provider.backend("zksf_mps").run(qc, shots=1000, certified=True)
job.error_info()["error_bound"]

Rejections are a feature

A simulation whose own error bound would be vacuous is refused rather than returned, and the refusal says what would make the circuit tractable.

from qiskit_zksf import JobRejected

try:
    job.result()
except JobRejected as exc:
    print(exc)   # "intractable classically at this structure: ... Options: ..."

Notes and limits

  • Several circuits become several jobs. The service has no batch endpoint yet, so backend.run([qc1, qc2]) submits them individually and each is billed separately.
  • No gradients. This is a cloud job queue with per-job billing, so parameter-shift differentiation through it would be expensive and slow. Use a local simulator for optimization loops and this for the runs whose accuracy you need to state.
  • Hardware costs real money and queues in hours, not seconds. Call estimate() first.

Links

Licence

MIT.

Release files for qiskit-zksf 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for qiskit-zksf 0.3.0
File Size Uploaded
qiskit_zksf-0.3.0.tar.gz 23.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for qiskit-zksf 0.3.0
File Interpreter ABI Platform
qiskit_zksf-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 40.1 kB

Release files / qiskit_zksf-0.3.0.tar.gz

Download URL qiskit_zksf-0.3.0.tar.gz
Size 23.0 kB
Tags Source
SHA-256 checksum
How to use checksums
881aa3d9d885f4f8e7b0313c963300f1edf32ee88ac050538327810f5e82cc36
BLAKE2b-256 checksum
How to use checksums
7dfc7da249391a3ab5ba99975c1ce9662e9826bdceccdc09ee2baff7fb0e233b
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 Sep 12, 2026.

Transparency log

Release files / qiskit_zksf-0.3.0-py3-none-any.whl

Download URL qiskit_zksf-0.3.0-py3-none-any.whl
Size 17.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c9711e6a7d75b11cd300cb0e4d1858d930bfae74d75edd5814b00432fe20383e
BLAKE2b-256 checksum
How to use checksums
8efa1894442d42cee30deec344e5be728d8c7e00ec4e59c35b9e2d21b7a9f54b
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 Sep 12, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page