Backends¶
The qtest.backends subpackage abstracts circuit execution behind
a single Backend protocol. Qiskit (default), Cirq,
and PennyLane implementations all ship in the box and are auto-registered
under the names "qiskit", "cirq", and "pennylane". Select one
per call (backend=CirqBackend()) or globally
(set_default_backend() / --qtest-backend).
Each backend operates on its SDK’s native circuit type — a
qiskit.QuantumCircuit, a cirq.Circuit, or a
pennylane.tape.QuantumScript respectively — and measurement-bitstring
endianness follows that SDK’s convention (Qiskit is little-endian; Cirq and
PennyLane put the lowest-index qubit leftmost). qtest’s
NoiseModel targets Qiskit Aer, so the Cirq and
PennyLane backends raise NotImplementedError if a noise_model
is supplied.
Install the optional SDKs with the matching extra:
pip install 'qtest-quantum[cirq]' # cirq-core
pip install 'qtest-quantum[pennylane]' # pennylane
Public API¶
Abstract base class for quantum circuit execution backends. |
|
|
Structural / resource metrics of a circuit, free of any execution. |
Qiskit simulator backend. |
|
Cirq state-vector simulator backend. |
|
PennyLane |
|
Instantiate and return a backend. |
|
Return a fresh instance of the current default backend. |
|
Set name as the default backend. |
|
Register backend_class under name. |
|
Return a sorted list of registered backend names. |
Reference¶
Backend abstraction layer for qtest.
Public API:
Backend— abstract interface every backend implements.CircuitResources— structural resource metrics of a circuit.QiskitBackend— concrete Qiskit adapter (default).CirqBackend— concrete Cirq adapter (registered as"cirq").PennyLaneBackend— concrete PennyLane adapter ("pennylane").get_backend(),get_default_backend(),set_default_backend(),register_backend(),list_available_backends()— registry helpers.
Importing this package does not import any quantum SDK; each SDK import happens lazily, the first time that backend’s execution method is called.
- class qtest.backends.Backend[source]¶
Bases:
ABCAbstract base class for quantum circuit execution backends.
- abstractmethod run_circuit(circuit, shots=None, seed=None, noise_model=None)[source]¶
Run circuit and return measurement counts.
- Parameters:
circuit (Any) – A circuit object native to the backend (e.g.
QuantumCircuit).shots (int | None) – Number of shots. If
None, the backend’s configured default is used.seed (int | None) – Optional seed for reproducible sampling.
noise_model (Any | None) – Optional
qtest.noise.NoiseModeldescribing the noise to apply during simulation.None(the default) runs an ideal, noiseless simulation. Backends that cannot simulate noise should raiseNotImplementedErrorwhen a non-Nonemodel is passed.
- Returns:
Mapping
{bitstring: count}whose values sum to shots.- Return type:
dict[str,int]
- abstractmethod get_statevector(circuit)[source]¶
Return the state vector produced by circuit (no measurement).
The returned array has
dtype=complexand length2**n_qubits.
- abstractmethod get_unitary(circuit)[source]¶
Return the unitary matrix of circuit.
The returned array has
dtype=complexand shape(2**n_qubits, 2**n_qubits). Raises if circuit contains non-unitary instructions (measurement, reset, …).
- get_density_matrix(circuit, noise_model=None)[source]¶
Return the density matrix produced by circuit.
With
noise_model=Nonethis is the pure-state projector \(|\psi\rangle\langle\psi|\); with a noise model it is the mixed state resulting from noisy evolution. The returned array hasdtype=complexand shape(2**n_qubits, 2**n_qubits).The default implementation raises
NotImplementedError; backends capable of density-matrix simulation override it.
- get_resources(circuit)[source]¶
Return structural resource metrics for circuit.
This is a static analysis of the circuit — no simulation is run, so it works on circuits of any width. The default implementation raises
NotImplementedError; backends able to introspect their native circuit type override it.- Parameters:
circuit (Any)
- Return type:
- abstract property supports_statevector: bool¶
Whether
get_statevector()/get_unitary()are supported.
- class qtest.backends.CirqBackend(shots=1024)[source]¶
Bases:
BackendCirq state-vector simulator backend.
- Parameters:
shots (int) – Default shot count for
run_circuit().
- property supports_statevector: bool¶
Whether
get_statevector()/get_unitary()are supported.
- run_circuit(circuit, shots=None, seed=None, noise_model=None)[source]¶
Run circuit and return measurement counts.
- Parameters:
circuit (Any) – A circuit object native to the backend (e.g.
QuantumCircuit).shots (int | None) – Number of shots. If
None, the backend’s configured default is used.seed (int | None) – Optional seed for reproducible sampling.
noise_model (Any | None) – Optional
qtest.noise.NoiseModeldescribing the noise to apply during simulation.None(the default) runs an ideal, noiseless simulation. Backends that cannot simulate noise should raiseNotImplementedErrorwhen a non-Nonemodel is passed.
- Returns:
Mapping
{bitstring: count}whose values sum to shots.- Return type:
dict[str,int]
- get_statevector(circuit)[source]¶
Return the state vector produced by circuit (no measurement).
The returned array has
dtype=complexand length2**n_qubits.
- get_unitary(circuit)[source]¶
Return the unitary matrix of circuit.
The returned array has
dtype=complexand shape(2**n_qubits, 2**n_qubits). Raises if circuit contains non-unitary instructions (measurement, reset, …).
- get_resources(circuit)[source]¶
Return structural resource metrics for circuit.
This is a static analysis of the circuit — no simulation is run, so it works on circuits of any width. The default implementation raises
NotImplementedError; backends able to introspect their native circuit type override it.- Parameters:
circuit (Any)
- Return type:
- class qtest.backends.PennyLaneBackend(shots=1024)[source]¶
Bases:
BackendPennyLane
default.qubitsimulator backend.- Parameters:
shots (int) – Default shot count for
run_circuit().
- property supports_statevector: bool¶
Whether
get_statevector()/get_unitary()are supported.
- run_circuit(circuit, shots=None, seed=None, noise_model=None)[source]¶
Run circuit and return measurement counts.
- Parameters:
circuit (Any) – A circuit object native to the backend (e.g.
QuantumCircuit).shots (int | None) – Number of shots. If
None, the backend’s configured default is used.seed (int | None) – Optional seed for reproducible sampling.
noise_model (Any | None) – Optional
qtest.noise.NoiseModeldescribing the noise to apply during simulation.None(the default) runs an ideal, noiseless simulation. Backends that cannot simulate noise should raiseNotImplementedErrorwhen a non-Nonemodel is passed.
- Returns:
Mapping
{bitstring: count}whose values sum to shots.- Return type:
dict[str,int]
- class qtest.backends.QiskitBackend(simulator_name='aer_simulator', shots=1024, optimization_level=1)[source]¶
Bases:
BackendQiskit simulator backend.
- Parameters:
simulator_name (str) – Cosmetic identifier reported via
name. The actual simulator chosen at run time isqiskit_aer.AerSimulatorif available, elseqiskit.providers.basic_provider.BasicSimulator.shots (int) – Default shot count used when
run_circuit()is called without an explicitshotsargument.optimization_level (int) – Default
transpileoptimisation level (one of0, 1, 2, 3).
Notes
The constructor arguments are defaults; per-call arguments to
run_circuit()override them. The backend keeps no other state between calls — two calls with identical arguments produce identical output (assuming the sameseed).- property supports_statevector: bool¶
Whether
get_statevector()/get_unitary()are supported.
- run_circuit(circuit, shots=None, seed=None, noise_model=None)[source]¶
Run circuit and return measurement counts.
- Parameters:
circuit (Any) – A circuit object native to the backend (e.g.
QuantumCircuit).shots (int | None) – Number of shots. If
None, the backend’s configured default is used.seed (int | None) – Optional seed for reproducible sampling.
noise_model (Any | None) – Optional
qtest.noise.NoiseModeldescribing the noise to apply during simulation.None(the default) runs an ideal, noiseless simulation. Backends that cannot simulate noise should raiseNotImplementedErrorwhen a non-Nonemodel is passed.
- Returns:
Mapping
{bitstring: count}whose values sum to shots.- Return type:
dict[str,int]
- get_statevector(circuit)[source]¶
Return the state vector produced by circuit (no measurement).
The returned array has
dtype=complexand length2**n_qubits.
- get_density_matrix(circuit, noise_model=None)[source]¶
Return the density matrix produced by circuit.
With
noise_model=Nonethis is the pure-state projector \(|\psi\rangle\langle\psi|\); with a noise model it is the mixed state resulting from noisy evolution. The returned array hasdtype=complexand shape(2**n_qubits, 2**n_qubits).The default implementation raises
NotImplementedError; backends capable of density-matrix simulation override it.
- get_unitary(circuit)[source]¶
Return the unitary matrix of circuit.
The returned array has
dtype=complexand shape(2**n_qubits, 2**n_qubits). Raises if circuit contains non-unitary instructions (measurement, reset, …).
- get_resources(circuit)[source]¶
Return structural resource metrics for circuit.
This is a static analysis of the circuit — no simulation is run, so it works on circuits of any width. The default implementation raises
NotImplementedError; backends able to introspect their native circuit type override it.- Parameters:
circuit (Any)
- Return type:
- qtest.backends.get_backend(name=None)[source]¶
Instantiate and return a backend.
If name is
None, the current default backend is used. RaisesKeyErrorif name is not registered, orRuntimeErrorif no default is set.
- qtest.backends.get_default_backend()[source]¶
Return a fresh instance of the current default backend.
- Return type:
- qtest.backends.register_backend(name, backend_class)[source]¶
Register backend_class under name.
Subsequent registrations under the same name overwrite the previous entry.
- qtest.backends.set_default_backend(name)[source]¶
Set name as the default backend. Must already be registered.
- Parameters:
name (str)
- Return type:
None
Backend protocol¶
Abstract backend interface for qtest.
A Backend is a stateless adapter that translates qtest’s public API
into a specific quantum SDK’s primitives (Qiskit today; Cirq / PennyLane
later). It exposes three core operations — running a circuit with
measurements, extracting the post-circuit state vector, and extracting the
circuit’s unitary — plus a couple of metadata properties.
Concrete backends MUST be free of cross-call mutable state: a given
configuration must produce the same output for the same input on every
call. Constructor arguments are immutable defaults; per-call overrides
(e.g. shots) are supported where applicable.
- class qtest.backends.base.CircuitResources(num_qubits, depth, size, gate_counts=<factory>, two_qubit_count=0, multi_qubit_count=0)[source]¶
Bases:
objectStructural / resource metrics of a circuit, free of any execution.
These describe how expensive a circuit is to run on hardware — the quantities transpilers and optimisers try to minimise — and are the basis for
qtest.assertions.resources.- Parameters:
- class qtest.backends.base.Backend[source]¶
Bases:
ABCAbstract base class for quantum circuit execution backends.
- abstractmethod run_circuit(circuit, shots=None, seed=None, noise_model=None)[source]¶
Run circuit and return measurement counts.
- Parameters:
circuit (Any) – A circuit object native to the backend (e.g.
QuantumCircuit).shots (int | None) – Number of shots. If
None, the backend’s configured default is used.seed (int | None) – Optional seed for reproducible sampling.
noise_model (Any | None) – Optional
qtest.noise.NoiseModeldescribing the noise to apply during simulation.None(the default) runs an ideal, noiseless simulation. Backends that cannot simulate noise should raiseNotImplementedErrorwhen a non-Nonemodel is passed.
- Returns:
Mapping
{bitstring: count}whose values sum to shots.- Return type:
dict[str,int]
- abstractmethod get_statevector(circuit)[source]¶
Return the state vector produced by circuit (no measurement).
The returned array has
dtype=complexand length2**n_qubits.
- abstractmethod get_unitary(circuit)[source]¶
Return the unitary matrix of circuit.
The returned array has
dtype=complexand shape(2**n_qubits, 2**n_qubits). Raises if circuit contains non-unitary instructions (measurement, reset, …).
- get_density_matrix(circuit, noise_model=None)[source]¶
Return the density matrix produced by circuit.
With
noise_model=Nonethis is the pure-state projector \(|\psi\rangle\langle\psi|\); with a noise model it is the mixed state resulting from noisy evolution. The returned array hasdtype=complexand shape(2**n_qubits, 2**n_qubits).The default implementation raises
NotImplementedError; backends capable of density-matrix simulation override it.
- get_resources(circuit)[source]¶
Return structural resource metrics for circuit.
This is a static analysis of the circuit — no simulation is run, so it works on circuits of any width. The default implementation raises
NotImplementedError; backends able to introspect their native circuit type override it.- Parameters:
circuit (Any)
- Return type:
- abstract property supports_statevector: bool¶
Whether
get_statevector()/get_unitary()are supported.
Registry¶
Module-level registry of available backends.
The registry stores a mapping {name: Backend subclass} and tracks which
name is the current default. The Qiskit backend is auto-registered on
import and set as the default.
Registration stores the class (a zero-argument-callable factory) so that
each call to get_backend() returns a fresh, stateless instance —
honouring the no-cross-call-state contract documented in
qtest.backends.base.Backend.
- qtest.backends.registry.register_backend(name, backend_class)[source]¶
Register backend_class under name.
Subsequent registrations under the same name overwrite the previous entry.
- qtest.backends.registry.get_backend(name=None)[source]¶
Instantiate and return a backend.
If name is
None, the current default backend is used. RaisesKeyErrorif name is not registered, orRuntimeErrorif no default is set.
- qtest.backends.registry.get_default_backend()[source]¶
Return a fresh instance of the current default backend.
- Return type:
Qiskit backend¶
Qiskit-based simulator backend for qtest.
This module is import-safe even when Qiskit is not installed: all
import qiskit ... calls are deferred to method bodies. Constructing
QiskitBackend does not require Qiskit; calling any of its execution
methods does.
Qiskit 1.0+ removed qiskit.execute and qiskit.BasicAer; we use
qiskit.transpile + backend.run(...) for sampling, and
qiskit.quantum_info.{Statevector, Operator} for state / unitary
extraction (no Aer required for those).
- class qtest.backends.qiskit_backend.QiskitBackend(simulator_name='aer_simulator', shots=1024, optimization_level=1)[source]¶
Bases:
BackendQiskit simulator backend.
- Parameters:
simulator_name (str) – Cosmetic identifier reported via
name. The actual simulator chosen at run time isqiskit_aer.AerSimulatorif available, elseqiskit.providers.basic_provider.BasicSimulator.shots (int) – Default shot count used when
run_circuit()is called without an explicitshotsargument.optimization_level (int) – Default
transpileoptimisation level (one of0, 1, 2, 3).
Notes
The constructor arguments are defaults; per-call arguments to
run_circuit()override them. The backend keeps no other state between calls — two calls with identical arguments produce identical output (assuming the sameseed).- property supports_statevector: bool¶
Whether
get_statevector()/get_unitary()are supported.
- run_circuit(circuit, shots=None, seed=None, noise_model=None)[source]¶
Run circuit and return measurement counts.
- Parameters:
circuit (Any) – A circuit object native to the backend (e.g.
QuantumCircuit).shots (int | None) – Number of shots. If
None, the backend’s configured default is used.seed (int | None) – Optional seed for reproducible sampling.
noise_model (Any | None) – Optional
qtest.noise.NoiseModeldescribing the noise to apply during simulation.None(the default) runs an ideal, noiseless simulation. Backends that cannot simulate noise should raiseNotImplementedErrorwhen a non-Nonemodel is passed.
- Returns:
Mapping
{bitstring: count}whose values sum to shots.- Return type:
dict[str,int]
- get_statevector(circuit)[source]¶
Return the state vector produced by circuit (no measurement).
The returned array has
dtype=complexand length2**n_qubits.
- get_density_matrix(circuit, noise_model=None)[source]¶
Return the density matrix produced by circuit.
With
noise_model=Nonethis is the pure-state projector \(|\psi\rangle\langle\psi|\); with a noise model it is the mixed state resulting from noisy evolution. The returned array hasdtype=complexand shape(2**n_qubits, 2**n_qubits).The default implementation raises
NotImplementedError; backends capable of density-matrix simulation override it.
- get_unitary(circuit)[source]¶
Return the unitary matrix of circuit.
The returned array has
dtype=complexand shape(2**n_qubits, 2**n_qubits). Raises if circuit contains non-unitary instructions (measurement, reset, …).
- get_resources(circuit)[source]¶
Return structural resource metrics for circuit.
This is a static analysis of the circuit — no simulation is run, so it works on circuits of any width. The default implementation raises
NotImplementedError; backends able to introspect their native circuit type override it.- Parameters:
circuit (Any)
- Return type:
Cirq backend¶
Cirq-based simulator backend for qtest.
Import-safe without Cirq: every import cirq is deferred to a method body,
so constructing CirqBackend (and importing this module) never requires
Cirq. Calling an execution method does.
Native circuit type¶
This backend operates on cirq.Circuit objects over
cirq.LineQubit (or any sortable qubit). Measurement bitstrings are
ordered with the lowest-index qubit leftmost (Cirq’s big-endian
convention), which is the opposite of Qiskit’s. Keep your expected dicts
consistent with whichever backend you select.
Noise¶
qtest’s NoiseModel is built on Qiskit Aer, so passing a
noise_model to this backend raises NotImplementedError. Noiseless
simulation is fully supported.
- class qtest.backends.cirq_backend.CirqBackend(shots=1024)[source]¶
Bases:
BackendCirq state-vector simulator backend.
- Parameters:
shots (int) – Default shot count for
run_circuit().
- property supports_statevector: bool¶
Whether
get_statevector()/get_unitary()are supported.
- run_circuit(circuit, shots=None, seed=None, noise_model=None)[source]¶
Run circuit and return measurement counts.
- Parameters:
circuit (Any) – A circuit object native to the backend (e.g.
QuantumCircuit).shots (int | None) – Number of shots. If
None, the backend’s configured default is used.seed (int | None) – Optional seed for reproducible sampling.
noise_model (Any | None) – Optional
qtest.noise.NoiseModeldescribing the noise to apply during simulation.None(the default) runs an ideal, noiseless simulation. Backends that cannot simulate noise should raiseNotImplementedErrorwhen a non-Nonemodel is passed.
- Returns:
Mapping
{bitstring: count}whose values sum to shots.- Return type:
dict[str,int]
- get_statevector(circuit)[source]¶
Return the state vector produced by circuit (no measurement).
The returned array has
dtype=complexand length2**n_qubits.
- get_unitary(circuit)[source]¶
Return the unitary matrix of circuit.
The returned array has
dtype=complexand shape(2**n_qubits, 2**n_qubits). Raises if circuit contains non-unitary instructions (measurement, reset, …).
- get_resources(circuit)[source]¶
Return structural resource metrics for circuit.
This is a static analysis of the circuit — no simulation is run, so it works on circuits of any width. The default implementation raises
NotImplementedError; backends able to introspect their native circuit type override it.- Parameters:
circuit (Any)
- Return type:
PennyLane backend¶
PennyLane-based simulator backend for qtest.
Import-safe without PennyLane: every import pennylane is deferred to a
method body, so constructing PennyLaneBackend (and importing this
module) never requires PennyLane.
Native circuit type¶
Unlike Qiskit/Cirq, PennyLane has no free-standing “circuit” object — programs
are expressed as quantum functions bound to a device. This backend therefore
operates on a pennylane.tape.QuantumScript (a.k.a. QuantumTape),
which is the closest device-independent container of operations. Build one as:
import pennylane as qml
tape = qml.tape.QuantumScript([qml.Hadamard(0), qml.CNOT([0, 1])])
Measurement bitstrings are ordered with the lowest-index wire leftmost. Existing measurements on the tape are ignored; qtest supplies its own.
Noise¶
qtest’s NoiseModel targets Qiskit Aer, so passing a
noise_model here raises NotImplementedError.
- class qtest.backends.pennylane_backend.PennyLaneBackend(shots=1024)[source]¶
Bases:
BackendPennyLane
default.qubitsimulator backend.- Parameters:
shots (int) – Default shot count for
run_circuit().
- property supports_statevector: bool¶
Whether
get_statevector()/get_unitary()are supported.
- run_circuit(circuit, shots=None, seed=None, noise_model=None)[source]¶
Run circuit and return measurement counts.
- Parameters:
circuit (Any) – A circuit object native to the backend (e.g.
QuantumCircuit).shots (int | None) – Number of shots. If
None, the backend’s configured default is used.seed (int | None) – Optional seed for reproducible sampling.
noise_model (Any | None) – Optional
qtest.noise.NoiseModeldescribing the noise to apply during simulation.None(the default) runs an ideal, noiseless simulation. Backends that cannot simulate noise should raiseNotImplementedErrorwhen a non-Nonemodel is passed.
- Returns:
Mapping
{bitstring: count}whose values sum to shots.- Return type:
dict[str,int]