Skip to content

Qiskit integration

The optional tensorweaver.qiskit module runs Qiskit circuits on the MPS engine. A QuantumCircuit is converted to a mimiq circuit and evolved, so your Qiskit code stays unchanged.

Install the extra:

pip install 'mimiq-tensorweaver[qiskit]'

Bit ordering

Qiskit's own convention applies to Qiskit objects: counts keys come back with the highest-indexed qubit on the left, the reverse of the little-endian ordering TensorWeaver uses natively. The conversion handles this, so read Qiskit results as Qiskit results.

Sampling

TensorWeaverBackend is a Qiskit BackendV2. Simulator options (bonddim, seed, algorithm, and the rest of the TwSimulator configuration) are fixed when the backend is built; run forwards only shots and seed.

from qiskit import QuantumCircuit
from tensorweaver.qiskit import TensorWeaverBackend

qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
qc.measure_all()

backend = TensorWeaverBackend(bonddim=64, seed=1)
counts = backend.run(qc, shots=4000).result().get_counts()

It also works under Qiskit's V2 primitives:

from qiskit.primitives import BackendSamplerV2

sampler = BackendSamplerV2(backend=backend)
result = sampler.run([qc], shots=4000).result()[0]
counts = result.data.meas.get_counts()

Expectation values

TensorWeaverEstimator is an EstimatorV2. Pauli terms on one or two qubits are read exactly from the MPS, with no shot noise. Terms on three or more qubits are estimated by sampling in the rotated basis, with the shot count derived from the requested precision (roughly 1/precision²); those terms carry a non-zero standard error.

from qiskit import QuantumCircuit
from qiskit.quantum_info import SparsePauliOp
from tensorweaver.qiskit import TensorWeaverEstimator

qc = QuantumCircuit(3)
qc.h(0)
qc.cx(0, 1)
qc.ry(0.7, 2)

obs = SparsePauliOp.from_list([("ZZI", 1.0), ("IIZ", 0.5), ("ZZZ", 0.25)])

estimator = TensorWeaverEstimator(bonddim=64, seed=1)
result = estimator.run([(qc, obs)], precision=0.005).result()[0]
print(result.data.evs, result.data.stds)

precision=0.0 makes the estimator fully exact, and is the default when run is called without one. Every observable must then consist only of one- and two-qubit Pauli terms: a longer term has no shot budget and raises ValueError.

To reuse a configured simulator across both interfaces, pass it in rather than repeating the options:

from tensorweaver import TwSimulator
from tensorweaver.qiskit import TensorWeaverEstimator

sim = TwSimulator(bonddim=128, algorithm="vmpoa")
estimator = TensorWeaverEstimator(simulator=sim, default_precision=0.01)

Gate coverage

Conversion covers the standard Qiskit gate set. Custom gates and gates with unbound parameters raise mimiq_qiskit.converter.UnsupportedGateError: bind the parameters and decompose custom gates before running.