Skip to main content

qiskit-maestro

Tests PyPI License: GPL v3+

Run your Qiskit code on the Maestro quantum circuit simulator by changing one or two lines. You get Maestro's statevector, matrix product state (MPS), stabilizer, extended stabilizer, density matrix, tensor network and Pauli propagation methods, on CPU or GPU, through the Qiskit interfaces you already use: a BackendV2, a SamplerV2 and an EstimatorV2.

Install

pip install qiskit-maestro

This installs Maestro (qoro-maestro) as well. It needs Python 3.10 or later and works with Qiskit 1.1 and later, including 2.x.

Switch from Aer

AerSimulator → MaestroBackend

from qiskit import QuantumCircuit, transpile
from qiskit_maestro import MaestroBackend   # was: from qiskit_aer import AerSimulator

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

backend = MaestroBackend()                  # was: AerSimulator()
counts = backend.run(transpile(qc, backend), shots=1000).result().get_counts()

MaestroBackend has a Target, so transpile and generate_preset_pass_manager(backend=backend) produce circuits it runs. Results come back as Aer returns them: counts, memory=True for per-shot bitstrings, and classical registers split by spaces. Qiskit's BackendSamplerV2(backend=MaestroBackend()) works too.

StatevectorSampler or Aer's SamplerV2 → MaestroSampler

from qiskit_maestro import MaestroSampler as Sampler   # was: from qiskit.primitives import StatevectorSampler as Sampler

result = Sampler(seed=1).run([qc], shots=1000).result()
counts = result[0].data.meas.get_counts()

PUBs, broadcasting, per-PUB shots and the result shapes are the same as StatevectorSampler's. Every parameter set of a PUB reuses one converted circuit, and the sets run in parallel.

StatevectorEstimator or Aer's EstimatorV2 → MaestroEstimator

import numpy as np
from qiskit.circuit.library import efficient_su2
from qiskit.quantum_info import SparsePauliOp
from qiskit_maestro import MaestroEstimator as Estimator   # was: from qiskit.primitives import StatevectorEstimator as Estimator

ansatz = efficient_su2(2, reps=1)
parameter_values = np.random.default_rng(0).uniform(0, np.pi, (10, ansatz.num_parameters))
hamiltonian = SparsePauliOp(["ZZ", "XI"], [1.0, 0.5])
evs = Estimator().run([(ansatz, hamiltonian, parameter_values)]).result()[0].data.evs  # shape (10,)

Expectation values are computed from the simulated state, not from shots, for every method. precision works as it does in StatevectorEstimator: 0 (the default) is exact, and a positive value adds Gaussian noise with that standard deviation, which is then reported in stds.

Coming from Aer's primitives? Their options={"backend_options": {...}, "run_options": {...}} argument is accepted as is.

Choose a method and a device

Pass options to MaestroBackend, MaestroSampler or MaestroEstimator. The names follow Aer's, and Aer's longer MPS option names work as aliases.

from qiskit_maestro import MaestroEstimator

estimator = MaestroEstimator(
    method="matrix_product_state",   # or "mps"
    max_bond_dimension=64,           # Aer: matrix_product_state_max_bond_dimension
    truncation_threshold=1e-10,      # Aer: matrix_product_state_truncation_threshold
)
Option Values Default
method "statevector", "matrix_product_state" ("mps"), "stabilizer", "extended_stabilizer", "density_matrix", "tensor_network", "pauli_propagation" "statevector"
device "CPU", "GPU" "CPU"
precision "double", "single" "double"
seed_simulator (seed on the primitives) integer random
max_bond_dimension integer, MPS only no cap
truncation_threshold discarded weight, MPS only Maestro's default
max_parallel_experiments threads for independent circuits and parameter sets; 0 chooses 0
maestro_options dict of any other maestro.SimulatorConfig field none

Maestro picks the fastest engine for a circuit by itself, so it may run a Clifford circuit you sent to "statevector" on the stabilizer engine. Results are unaffected, and each result's metadata records what actually ran.

Time evolution

MaestroEstimator runs time evolution on one persistent simulator, using Maestro's incremental evolution. If the PUBs of one run call are the same initial circuit followed by 0, 1, 2, ... repetitions of one step, as when each time point of a Trotter evolution is its own circuit, Maestro simulates the longest circuit once and reads every time point on the way. Measuring at every one of N steps then costs N steps instead of about N²/2. Circuits built with PauliEvolutionGate(..., synthesis=LieTrotter(reps=k)) are recognised too.

from qiskit import QuantumCircuit
from qiskit.quantum_info import SparsePauliOp
from qiskit_maestro import MaestroEstimator

n = 50
step = QuantumCircuit(n)  # One Trotter step of an Ising chain.
for start in (0, 1):
    for q in range(start, n - 1, 2):
        step.rzz(-0.2, q, q + 1)
step.rx(-0.14, range(n))
magnetisation = SparsePauliOp.from_sparse_list([("Z", [q], 1 / n) for q in range(n)], n)
estimator = MaestroEstimator(method="matrix_product_state")

# One circuit per time point, as you'd write it for any estimator.
circuits, circuit = [], QuantumCircuit(n)
for k in range(21):
    circuits.append(circuit.copy())
    circuit.compose(step, inplace=True)
results = estimator.run([(c, magnetisation) for c in circuits]).result()

# Or give the step directly, without building a circuit per time point.
evolution = estimator.run_evolution(QuantumCircuit(n), step, magnetisation, steps=range(21))
evs = evolution.result()[0].data.evs  # One value per step: shape (21,).

Each result's metadata says whether incremental evolution was used. Pass incremental_evolution=False to simulate every circuit from the start. It isn't used for PUBs with parameter arrays, circuits that reset qubits, or the tensor network and Pauli propagation methods, which gain nothing from it.

GPU

device="GPU" runs on Maestro's GPU backend (statevector, MPS, tensor network and Pauli propagation). You need GPU access: see Get GPU access. Maestro reads the licence key from MAESTRO_LICENSE_KEY itself. If no GPU is available or the licence isn't accepted, qiskit-maestro raises MaestroGpuError; it never falls back to the CPU silently.

Bit order

Maestro puts qubit 0 on the left of bitstrings and Pauli strings; Qiskit puts it on the right. qiskit-maestro converts at the boundary, so everything you see (counts, memory, BitArrays, observables) uses Qiskit's order.

What's supported, and what isn't yet

Supported:

  • Every Qiskit gate. Maestro's 28 native gates run directly, and others (rzz, ecr, unitary, PauliEvolutionGate, library circuits and so on) are expanded through their Qiskit definitions.
  • Mid-circuit measurement and reset.
  • if_test with an optional else, on one clbit or a register value, with gates and measurements in the branches. In Qiskit 1.x, c_if as well.
  • Parameterised circuits, with Qiskit's broadcasting rules.
  • SparseObservable projector terms (0, 1, +, -, r, l) in the Estimator (Qiskit 2.x).

Not supported yet:

  • Noise models. Aer's NoiseModel isn't translated. Maestro has its own noise models, which this package doesn't expose yet.
  • Some classical control. for_loop, while_loop, switch and classical expressions beyond "bit is set" and "register equals value" aren't supported. Casts are read as Qiskit does: a cast to a narrower Uint keeps the low bits. A cast of a multi-bit register to Bool (a non-zero test) isn't supported. Neither are nested if_test blocks, a reset inside if_test, or an else branch on a multi-bit condition. Each raises UnsupportedInstructionError naming the instruction.
  • Measurements in Estimator circuits. As in StatevectorEstimator, they raise an error. Resets are allowed: statevector and MPS follow one random outcome, as StatevectorEstimator does, and density matrix is exact.
  • save_statevector and other Aer save_* instructions. Use the Estimator, or Maestro's own get_statevector.
  • Aer methods without a Maestro equivalent: unitary, superop. The automatic method name isn't accepted; leave method out instead.
  • dt timing. Delays are dropped, since they don't change a noiseless simulation.
  • Shot order. Maestro returns counts. Per-shot memory and BitArray shots are those counts in random order. That's exact in distribution, since shots are independent, but it isn't the order Maestro simulated them in.

License

GPL-3.0-or-later. See LICENSE.

Metadata

Release files for qiskit-maestro 0.1.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-maestro 0.1.0
File Size Uploaded Provenance Actions
qiskit_maestro-0.1.0.tar.gz 64.1 kB With provenance Details for qiskit_maestro-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for qiskit-maestro 0.1.0
File Interpreter ABI Platform Actions
qiskit_maestro-0.1.0-py3-none-any.whl Python 3 none any Details for qiskit_maestro-0.1.0-py3-none-any.whl

Total release size: 109.2 kB

Release files / qiskit_maestro-0.1.0.tar.gz

Download URL qiskit_maestro-0.1.0.tar.gz
Size 64.1 kB
Tags Source
SHA-256 checksum
How to use checksums
ae08151b868553926b3a913787dffb81316e3ba610b72f21fdde6ad29a91bd7e
BLAKE2b-256 checksum
How to use checksums
a73a2139a16f18b126ee8a86592787424d11a0a30cd54c9b3d4176cc745244ec
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Nov 1, 2026.

Transparency log

Release files / qiskit_maestro-0.1.0-py3-none-any.whl

Download URL qiskit_maestro-0.1.0-py3-none-any.whl
Size 45.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a2fed446e059625e443434346aae0f48a53757e5b83e3d1c20cad0084b8dd767
BLAKE2b-256 checksum
How to use checksums
3b0c77aff1d24f796ceafeb9aa393d6aa6cd64f110a4b9ea8bf813fe0444aaa7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Nov 1, 2026.

Transparency log

Security for qiskit-maestro 0.1.0

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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for qiskit_maestro-0.1.0.tar.gz

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 Nov 1, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

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