qiskit

Dependencies

Install with pip install qc-executor[qiskit-full]. Requires:

  • qiskit>=2.5.2

  • packaging>=21.0

  • qiskit-aer>=0.17.0

  • qiskit-ibm-runtime>=0.37.0

Executor

class qc_executor.qiskit.QiskitExecutor(backend='statevector', shots=None, seed=None, log_file=None, log_level='WARNING', caching=None, cache_dir='cache', max_cache_size=4096, execution_mode='job', options=None, primitive_wrapper=None)[source]

Bases: ExecutorBase

Class for executing Qiskit circuits.

Supports local simulation ("statevector", "aer") and execution on real IBM Quantum hardware or noise-aware fake backends via qiskit-ibm-runtime.

The backend parameter is the single entry point and accepts all supported configurations:

  • "statevector" — Qiskit’s reference primitives (StatevectorEstimator/StatevectorSampler): exact for shots=None, otherwise an analytic Gaussian noise model on top of the exact statevector.

  • "aer" — the general-purpose AerSimulator: real shot-based sampling instead of "statevector"’s analytic noise model, so the two are not necessarily numerically equivalent even though both target the same exact state. Aer chooses its simulation method per circuit; pass the simulator itself, for instance AerSimulator(method="statevector"), to pin one.

  • "aer_statevector" — "aer" pinned to AerSimulator(method="statevector").

  • A Backend / BackendV2 instance (e.g. from QiskitRuntimeService or fake_provider).

  • A qiskit_ibm_runtime.Session or Batch — ownership is transferred to the executor, which closes it on exit.

  • A pre-configured Qiskit primitive (BaseSamplerV2 / BaseEstimatorV2 or their V1 equivalents) — injected directly; the missing counterpart primitive is created automatically when possible.

Context-manager use is strongly recommended for real IBM backends to guarantee that sessions are properly closed:

with QiskitExecutor(backend=ibm_backend, execution_mode="session") as exe:
    result = exe.expectation_value(circuit, observable, theta=params)
Parameters:
  • backend (str | Backend | Session | Batch | BaseEstimatorV1 | BaseSamplerV1 | BaseEstimatorV2 | BaseSamplerV2) – Backend to use for execution. Accepts: "statevector" (default), "aer" or "aer_statevector", a Qiskit Backend instance (IBM hardware or fake), a qiskit_ibm_runtime.Session / Batch, or a pre-configured Qiskit primitive (BaseSamplerV1/V2 / BaseEstimatorV1/V2).

  • shots (int | None, optional) – Number of shots for sampling.

  • seed (int | None, optional) – Random seed for reproducibility.

  • log_file (str | None, optional) – Path to the log file.

  • log_level (str, optional) – Logging level.

  • caching (bool | None, optional) – Whether to use in-memory caching.

  • cache_dir (str, optional) – Directory for caching.

  • max_cache_size (int | None, optional) – Maximum number of entries kept in each in-memory cache; None makes them unbounded.

  • execution_mode (str, optional) – "job" (default), "session", or "batch". Only relevant for real IBM Quantum backends. Use "session" for iterative algorithms (VQE, QAOA) and "batch" for independent parallel jobs.

  • options (dict | None, optional) – Options forwarded to IBM Runtime primitives (e.g. {"resilience_level": 1}). Ignored for local backends.

  • primitive_wrapper (callable | None, optional) – wrapper(primitive, kind) -> primitive, with kind either "estimator" or "sampler". Applied to every primitive this executor (re)builds - on initial construction, after a runtime session renewal, and for lazily deferred session primitives - so a host application can layer cross-cutting concerns (retry, disk caching, seeding, …) on top of execution without ever holding a primitive itself. The wrapper’s return value must be a genuine instance of the same base class as the primitive it was given (BaseEstimatorV1/ BaseEstimatorV2 for an estimator, BaseSamplerV1/ BaseSamplerV2 for a sampler) - qc_executor’s own OpTree evaluation dispatches on isinstance() of exactly those classes, so duck-typing run() alone is not enough. See raw_estimator/raw_sampler for the underlying, undecorated primitive.

property shots: int | None

Return the number of shots.

property remote: bool

Return True if the executor targets a remote backend.

property ibm_quantum: bool

Return True if the executor targets a real IBM Quantum device.

property session

Return the active runtime Session or Batch, or None.

property backend

Return the resolved Qiskit backend, or None.

None for exact statevector simulation (backend="statevector", shots=None) and for an injected primitive/Session from which no backend context could be recovered.

property estimator

Return the Qiskit estimator primitive used for execution.

For real IBM Quantum hardware, this refreshes the underlying runtime session and primitives first if the session has expired since the last access - safe to call repeatedly across a long-running loop without needing a with block.

property sampler

Return the Qiskit sampler primitive used for execution.

For real IBM Quantum hardware, this refreshes the underlying runtime session and primitives first if the session has expired since the last access - safe to call repeatedly across a long-running loop without needing a with block.

property raw_estimator

Return the raw (undecorated) Qiskit estimator primitive.

Unlike estimator, which returns whatever a registered primitive_wrapper turned the primitive into (see the constructor), this is always the genuine Qiskit primitive qc_executor itself constructed - useful for host-side introspection (e.g. reading its concrete type or default options).

property raw_sampler

Return the raw (undecorated) Qiskit sampler primitive.

Unlike sampler, which returns whatever a registered primitive_wrapper turned the primitive into (see the constructor), this is always the genuine Qiskit primitive qc_executor itself constructed - useful for host-side introspection (e.g. reading its concrete type or default options).

create_session()[source]

Explicitly (re)create the runtime session now, instead of waiting for the first execution to trigger it lazily.

A no-op when this executor doesn’t manage its own session (local simulators, fake backends, or real IBM Quantum hardware in "job" execution mode all build their primitives without one).

Return type:

None

close_session()[source]

Close the current runtime session/batch if one is active.

Session ownership is always managed by the executor, including injected Session / Batch objects.

Return type:

None

classmethod get_accepted_backend_types()[source]

Return all types accepted as the backend argument.

Covers: * Qiskit local backends (Backend / BackendV2) * Qiskit statevector primitives (StatevectorEstimator, StatevectorSampler) * Qiskit local primitive base classes (V1 and V2) * IBM Runtime Session / Batch (when qiskit-ibm-runtime is installed) * IBM Runtime primitive classes (V1 and V2, version-gated)

Dummy sentinel classes defined when optional dependencies are absent are intentionally excluded so that isinstance checks never yield false positives.

Return type:

list[type]

classmethod get_accepted_backend_aliases()[source]

Return string aliases accepted by this executor in Executor.create.

Return type:

list[str]

Native abstraction

Circuit

class qc_executor.qiskit.QiskitCircuit(num_qubits=0, num_clbits=0, *, _ir=None, _native=None)[source]

Bases: QuantumCircuitBase

A quantum circuit that compiles to Qiskit.

Built like any other circuit – QiskitCircuit(2) then circuit.h(0) – or converted from an existing one with from_quantum_circuit(). The Qiskit circuit is produced on demand and rebuilt whenever the instruction store changes.

A pre-built Qiskit circuit can also be adopted through from_qiskit(), which stores it directly instead of deriving it; see that method for why.

Parameters:
  • num_qubits (int) – Number of qubits in the circuit.

  • num_clbits (int) – Number of classical bits, for mid-circuit measurement.

  • _ir (CircuitIR | None) – Adopt this instruction store instead of starting empty.

  • _native (Any) – Adopt this Qiskit circuit instead of compiling one.

classmethod supported_opcodes()[source]

Return the opcodes the Qiskit bridge emits directly.

Return type:

frozenset

classmethod from_quantum_circuit(circuit)[source]

Convert a circuit, or adopt a Qiskit circuit passed directly.

Parameters:

circuit (Any) – A QuantumCircuitBase or a raw qiskit.QuantumCircuit.

Return type:

QiskitCircuit

Returns:

The circuit in this native form.

classmethod from_qiskit(qiskit_circuit)[source]

Adopt an existing Qiskit circuit without deriving it from the IR.

The circuit is stored as-is rather than imported, because the ones that arrive here cannot be expressed in the IR: an ISA-transpiled circuit carries a global phase, a TranspileLayout, possibly Delay and IfElseOp instructions, and is widened to the backend’s full qubit count. Round-tripping it would silently discard all of that, so the instruction store is left empty and this object is a carrier for the compiled circuit.

The result runs on the Qiskit backend only: its instruction store is empty, so converting it to another backend’s circuit yields an empty circuit. To run a Qiskit circuit everywhere, import it with QuantumCircuit.from_qiskit.

Parameters:

qiskit_circuit – The Qiskit circuit to adopt.

Return type:

QiskitCircuit

Returns:

A QiskitCircuit wrapping it.

property qiskit_circuit

The underlying Qiskit circuit.

property num_qubits: int

Number of qubits in the circuit.

property free_parameters: set

The Qiskit parameter objects appearing in the compiled circuit.

property parameter_dimensions: dict

Number of elements used from each Qiskit parameter vector.

property parameter_names: List[str]

Names of the Qiskit parameter vectors used by the circuit.

bind_parameters(parameter_values)[source]

Bind values and return the resulting Qiskit circuit.

Distinct from assign_parameters(), which stays in this abstraction and returns a QiskitCircuit.

Parameters:

parameter_values (dict) – Values keyed by parameter name.

Returns:

The bound qiskit.QuantumCircuit.

copy()[source]

Return an independent copy of this circuit.

Return type:

QiskitCircuit

fingerprint()[source]

Return a stable digest of the circuit’s content.

Return type:

bytes

Operator

class qc_executor.qiskit.QiskitOperator(paulis=None, coeffs=None, num_qubits=None, *, _ir=None)[source]

Bases: QuantumOperatorBase

An observable that compiles to Qiskit’s SparsePauliOp.

Built like any other operator – QiskitOperator(["ZI"], [1.0]) – or converted from an existing one with from_quantum_operator(). The SparsePauliOp is produced on demand, so the whole inherited algebra (compose(), adjoint(), apply_layout(), …) is available and stays in this abstraction.

Parameters:
  • paulis (Optional[Sequence[str]]) – Pauli labels, qubit 0 leftmost.

  • coeffs (Optional[Sequence[Any]]) – One coefficient per label.

  • num_qubits (int | None) – Width, required only when no labels are given.

  • _ir (PauliIR | None) – Adopt this representation instead of building one.

classmethod from_quantum_operator(operator, **options)[source]

Convert an operator, or import a SparsePauliOp passed directly.

Parameters:
  • operator (Any) – A QuantumOperatorBase or a raw qiskit.quantum_info.SparsePauliOp.

  • **options – Accepted for interface parity; unused.

Return type:

QiskitOperator

Returns:

The operator in this native form.

property qiskit_operator

The underlying Qiskit SparsePauliOp.

property free_parameters: set

The Qiskit parameter objects appearing in the compiled operator.

property parameter_dimensions: dict

Number of elements used from each Qiskit parameter vector.

property parameter_names: List[str]

Names of the Qiskit parameter vectors used by the operator.

bind_parameters(parameter_values)[source]

Bind values and return the resulting Qiskit operator.

Distinct from assign_parameters(), which stays in this abstraction and returns a QiskitOperator.

Parameters:

parameter_values (dict) – Values keyed by parameter name.

Returns:

The bound SparsePauliOp.