spin_pulse

SpinPulse is an open-source python package for simulating silicon based spin qubits at the pulse-level.

Modules

spin_pulse.transpilation

The transpilation module provides a set of classes that enable the simulation of quantum circuits defined in Qiskit on silicon-based spin-qubit hardware models.

spin_pulse.environment

The environment module provides a set of classes for defining and configuring a quantum experimental environment tailored to spin-qubit systems.

spin_pulse.characterization

The characterization module provides a set of functions for characterizing spin-qubit control operations and quantifying noise strength.

Re-exported objects

The following objects can be directly imported from spin_pulse even if they are implemented in submodules.

DynamicalDecoupling

Enumeration of supported dynamical decoupling sequences.

ExperimentalEnvironment

Contain a quantum experimental environment with configurable noise models.

HardwareSpecs

Defines the hardware specifications for a spin qubit device model.

PulseCircuit

Pulse-level representation of a quantum circuit.

Shape

Enumeration of pulse envelope shapes.

Subpackages

Submodules

Classes

ExperimentalEnvironment

Contain a quantum experimental environment with configurable noise models.

DynamicalDecoupling

Enumeration of supported dynamical decoupling sequences.

HardwareSpecs

Defines the hardware specifications for a spin qubit device model.

Shape

Enumeration of pulse envelope shapes.

PulseCircuit

Pulse-level representation of a quantum circuit.

Package Contents

class spin_pulse.ExperimentalEnvironment(hardware_specs, noise_type=NoiseType.PINK, T2S=100.0, TJS=None, duration=2**10, only_idle=False, segment_duration=2**10, seed=None)[source]

Contain a quantum experimental environment with configurable noise models.

- hardware_specs

HardwareSpecs class, that defines the hardware settings.

Type:

class

- noise_type

Type of noise to simulate. Must be “pink”, “white”, or “quasistatic”.

Type:

NoiseType

- T2S

Characteristic time of individual qubits.

Type:

float

- TJS

Characteristic time of coupled two-qubit system at maximal J coupling without noise on the qubit’s frequency.

Type:

float or None

- duration

Total duration of the simulation.

Type:

int

- segment_duration

Duration of each noise segment; used to partition the time trace.

Type:

int

- only_idle

Flag to apply noise only to idle qubits.

Type:

bool

- time_traces

List of time traces for each qubit.

Type:

list[float]

- time_traces_coupling

List of time traces for coupling noise for each pair of qubits (if TJS is set).

Type:

list[float]

- seed

seed integer for random number generation. If not specified, no seed used.

Type:

int or None

Initialize the ExperimentalEnvironment with specified noise characteristics and simulation parameters.

Parameters:
  • hardware_specs (class) – HardwareSpecs class, that defines the hardware settings.

  • noise_type (NoiseType) – Type of noise to simulate. Must be “pink”, “white”, or “quasistatic”.

  • T2S (float) – Characteristic time of individual qubits.

  • TJS (float or None) – Characteristic time of coupled two-qubit system at maximal J coupling with no noise on the qubit’s frequency.

  • duration (int) – Total duration of the simulation.

  • only_idle (bool) – Flag to apply noise only to idle qubits.

  • segment_duration (int) – Duration of each noise segment; used to partition the time trace.

  • seed (int or None) – seed integer for random number generation. If not specified, no seed used.

Raises:

ValueError – If an invalid noise_type is provided.

noise_generator: type[spin_pulse.environment.noise.WhiteNoiseTimeTrace] | type[spin_pulse.environment.noise.QuasistaticNoiseTimeTrace] | type[spin_pulse.environment.noise.PinkNoiseTimeTrace]
hardware_specs: spin_pulse.transpilation.hardware_specs.HardwareSpecs
noise_type: spin_pulse.environment.noise.NoiseType
T2S: float = 100.0
TJS: float | None = None
duration: int = 1024
segment_duration: int = 1024
seed: int | None = None
only_idle = False
generate_time_traces()[source]

Generate noise time traces for each qubit’s frequency and J coupling to each pair of qubits if TJS is defined.

Behavior:

For each qubit, instantiate a noise generator using the selected noise_type. The generator uses T2S, duration, and segment_duration to produce a time trace. If TJS is provided, generate additional time traces for J coupling noise for each pair of qubits.

Effects:

Populate self.time_traces with one noise trace per qubit. If TJS is set, populate self.time_traces_coupling with one trace per pair of qubits (n-1 traces for n qubits).

class spin_pulse.DynamicalDecoupling(*args, **kwds)[source]

Bases: enum.Enum

Enumeration of supported dynamical decoupling sequences.

This enumeration identifies the available pulse-based methods used to mitigate phase noise in spin qubit experiments. The selected sequence determines how control pulses are applied during idle periods in order to reduce the effect of low-frequency noise.

- FULL_DRIVE

Continuous driving of the qubit during the idle period.

- SPIN_ECHO

Single refocusing pulse applied at the midpoint of the idle period.

FULL_DRIVE = 'full_drive'
SPIN_ECHO = 'spin_echo'
class spin_pulse.HardwareSpecs(num_qubits, B_field, delta, J_coupling, rotation_shape, ramp_duration=1, coeff_duration=5, dynamical_decoupling=None, optim=0)[source]

Defines the hardware specifications for a spin qubit device model.

This class stores all physical and control parameters required to build pulse instructions, generate rotation gates, and configure backend-level compilation. It also defines the available couplings, supported gate set, and optional dynamical decoupling strategy. The specifications in this object determine how qubit operations and timing constraints are modeled throughout the simulation workflow.

- rotation_generator

Class used to generate rotation instructions based on the selected pulse shape.

Type:

RotationInstruction

- num_qubits

Number of qubits in the device model.

Type:

int

- J_coupling

Maximum coupling strength between adjacent qubits.

Type:

float

- fields

Dictionary mapping interaction types (“x”, “y”, “z”, “Heisenberg”) to their corresponding field strengths.

Type:

dict

- rotation_shape

Shape of the pulses used for qubit control.

Type:

Shape

- coeff_duration

Duration coefficient for Gaussian pulses when applicable.

Type:

int

- ramp_duration

Duration of the ramp used in square pulses.

Type:

int

- first_pass

Preset first-stage Qiskit pass manager.

Type:

PassManager

- second_pass

Additional optimization pass manager.

Type:

PassManager

- dynamical_decoupling

Optional dynamical decoupling sequence applied to idle qubits.

Type:

DynamicalDecoupling | None

Initialize the HardwareSpecs object that defines the hardware specifications.

Parameters:
  • num_qubits (int) – Number of qubits considered.

  • B_field (float) – Maximal magnetic field strength.

  • delta (float) – Maximal energy difference between two qubits.

  • J_coupling (float) – Maximal coupling strength between two qubit.

  • rotation_shape (Shape) – Pulse shape used for qubit manipulation.

  • ramp_duration (int, optional) – Duration of the pulse ramp for square pulse. Default is 1.

  • coeff_duration (int, optional) – Duration coefficient for Gaussian pulses. Default is 5.

  • dynamical_decoupling (DynamicalDecoupling, optional) – If not None, defines the dynamical decoupling sequence to be applied to Idle qubits.

  • optim (int)

rotation_generator: type[spin_pulse.transpilation.instructions.RotationInstruction]
num_qubits: int
J_coupling: float
fields: dict[str, float]
rotation_shape: Shape
ramp_duration: int = 1
first_pass
second_pass
dynamical_decoupling: spin_pulse.transpilation.dynamical_decoupling.DynamicalDecoupling | None = None
gate_transpile(circ)[source]

Transpile a quantum circuit into an ISA circuit using hardware specifications.

Parameters:

circ (qiskit.QuantumCircuit) – The quantum circuit to be converted.

Returns:

The ISA quantum circuit composed of spin qubit native gates.

Return type:

qiskit.QuantumCircuit

class spin_pulse.Shape(*args, **kwds)[source]

Bases: enum.Enum

Enumeration of pulse envelope shapes.

This enum defines the functional form of the pulse envelope used for control operations in spin-qubit pulse sequences.

GAUSSIAN = 'gaussian'

Gaussian-shaped pulse envelope.

SQUARE = 'square'

Square (rectangular) pulse envelope.

class spin_pulse.PulseCircuit(circ, qubits, pulse_layers, hardware_specs, exp_env=None)[source]

Pulse-level representation of a quantum circuit.

A PulseCircuit stores a layered decomposition of a qiskit.QuantumCircuit into PulseLayer objects and, optionally, a stochastic noise environment. It provides utilities to visualize the pulse schedule, convert it back to a gate-level circuit, and compute fidelities or average channels under sampled noise realizations.

- original_circ

Original quantum circuit from which the PulseCircuit was constructed.

Type:

qiskit.QuantumCircuit

- num_qubits

Number of qubits in the circuit.

Type:

int

- qubits

Ordered list of qubits acted on by the circuit.

Type:

list[qiskit.circuit.Qubit]

- pulse_layers

Ordered list of pulse layers that implement the circuit at the pulse level.

Type:

list[PulseLayer]

- n_layers

Number of pulse layers.

Type:

int

- duration

Total duration of the pulse circuit, given by the sum of all layer durations (in the discrete time unit of the model).

Type:

int

- t_lab

Current position in the laboratory time axis, used to attach successive noise time traces when averaging over samples.

Type:

int

Initialize a PulseCircuit from pulse layers.

The constructor records the original circuit, the list of qubits and the sequence of PulseLayer objects. It computes the total duration, assigns starting times to all layers and computes a dynamical decoupling sequence according to the hardware specifications. If an ExperimentalEnvironment is provided, noise time traces are attached to the circuit and its layers. Optionally, a container for storing per-sample time series can be created.

Parameters:
  • circ (QuantumCircuit) – Original quantum circuit represented at the pulse level.

  • qubits (list[qiskit.circuit.Qubit]) – Ordered list of qubits involved in the circuit.

  • pulse_layers (list[PulseLayer]) – Pulse layers that realize the circuit in time order.

  • hardware_specs (HardwareSpecs) – Hardware configuration specifying fields, couplings and dynamical decoupling options.

  • exp_env (ExperimentalEnvironment | None) – Noise environment from which time traces are drawn and attached to this circuit. If None, no noise trace is attached.

original_circ: qiskit.QuantumCircuit
qubits: list[qiskit.circuit.Qubit]
num_qubits
pulse_layers
n_layers
duration
t_lab = 0
classmethod from_circuit(circ, hardware_specs, exp_env=None)[source]

Construct a PulseCircuit from a qiskit.QuantumCircuit.

The input is first converted to a qiskit.dagcircuit.DAGCircuit then all barrier and measurement gate are removed, and each DAG layer is translated into a PulseLayer using the hardware specifications. Empty layers (containing only barriers) are skipped. The resulting list of pulse layers is used to build a PulseCircuit.

Parameters:
  • circ (qiskit.QuantumCircuit) – Circuit to translate into pulse layers.

  • hardware_specs (HardwareSpecs) – Hardware specification used to map gate operations to pulse sequences.

  • exp_env (ExperimentalEnvironment | None) – Experimental environment providing noise specification and noise time traces. If None, no noise is attached to the pulses.

Returns:

A pulse-level representation of the input circuit.

Return type:

PulseCircuit

classmethod from_dag_circuit(dag, hardware_specs, exp_env=None, original_circuit=None)[source]

Construct a PulseCircuit from a qiskit.dagcircuit.DAGCircuit.

The input circuit is first stripped of measurements and barrier, if present. Then each DAG layer is translated into a PulseLayer using the hardware specifications. Empty layers (containing only barriers) are skipped. The resulting list of pulse layers is used to build a PulseCircuit.

Parameters:
  • dag (qiskit.dagcircuit.DAGCircuit) – Circuit to translate into pulse layers.

  • hardware_specs (HardwareSpecs) – Hardware specification used to map gate operations to pulse sequences.

  • exp_env (ExperimentalEnvironment | None) – Experimental environment providing noise specification and noise time traces. If None, no noise is attached to the pulses.

  • original_circuit (qiskit.QuantumCircuit | None)

Returns:

A pulse-level representation of the input circuit.

Return type:

PulseCircuit

assign_starting_times()[source]

Assign a starting time to each pulse layer to synchronize the different layers and pulse instructions.

The starting time t_start of each PulseLayer is computed as the cumulative duration of all previous layers, with the first layer starting at time zero. This defines a global time axis for the PulseCircuit.

plot(hardware_specs=None, label_gates=True)[source]

Plot the pulse schedule of the circuit.

This method creates a multi-panel matplotlib figure showing, for each layer, the one-qubit and two-qubit pulse envelopes applied to each qubit and coupling. The vertical scale is chosen consistently with the hardware field and coupling amplitudes if given.

Parameters:
  • hardware_specs (HardwareSpecs | None) – Hardware specification used to set the limits of manipulation parameter amplitudes. If None, default symmetric limits are used.

  • label_gates (bool) – If True, gate labels are shown.

to_circuit(measure_all=False)[source]

Convert the pulse circuit back to a qiskit.QuantumCircuit.

Each PulseLayer is converted into equivalent circuit that are composed into a copy of the original circuit structure. Optionally, a final measurement on all qubits is added.

Parameters:

measure_all (bool) – If True, all qubits are measured at the end of the reconstructed circuit.

Returns:

A circuit implementing the same unitary evolution as the PulseCircuit (up to numerical approximations).

Return type:

qiskit.QuantumCircuit

circuit_samples(exp_env=None)[source]

Compute the number of noisy circuit samples that can be obtained with the given environment.

The number of circuit samples is given by the integer ratio between the environment duration and the pulse-circuit duration. If no environment is provided, a single sample is assumed.

Parameters:

exp_env (ExperimentalEnvironment | None) – Experimental environment providing the total duration.

Returns:

Number of non-overlapping samples that can be drawn from the duration of the experiment.

Return type:

int

get_logical_bitstring(physical_bistring)[source]

Restore the original logical qubit layout before transpilation. During Qiskit transpilation process, the qubit register may be reordered to produce an optimized physical layout that minimizes gate costs. To recover the logical bitstring and interpret measurement outcomes correctly, it is necessary to invert this remapping and reconstruct the initial logical ordering of the qubits.

The mapping is derived from the layout associated with the original circuit used to build the PulseCircuit. If a TranspileLayout is present, the final index layout is used. If only a Layout is available, its permutation is used and a warning is emitted, as this typically indicates that the circuit was not transpiled. If no layout information is present, the physical and logical orders are assumed to coincide and a warning is emitted.

Parameters:

physical_bistring (str) – Bitstring obtained from a measurement in the physical qubit ordering.

Returns:

Bitstring reordered into the logical qubit basis.

Return type:

str

averaging_over_samples(f, exp_env=None, *args)[source]

Estimate the average value over as many noisy samples as the experimental environment allows it, of a user-provided function using the pulse circuit.

This method repeatedly attaches new pieces of the noise time traces from the experimental environment to the PulseCircuit and evaluates a user-provided function f(self, *args) for each realization. The results are averaged over all samples, effectively performing a Monte Carlo average over noise trajectories.

Parameters:
  • f (Callable) – Function that takes the PulseCircuit as first argument and returns a numerical quantity to be averaged.

  • exp_env (ExperimentalEnvironment | None) – Noise environment from which time traces are drawn. If None, a single deterministic evaluation is performed.

  • *Parameters – Additional positional arguments forwarded to f.

Returns:

The sample-averaged value of f(self, *args).

Return type:

Any

run_experiment(exp_env, simulator=AerSimulator())[source]

Simulate single-shot measurement on noisy instances of the circuit.

This method repeatedly attaches new pieces of the noise time traces from the experimental environment to the PulseCircuit and simulates with MPS method a single-shot measurement thanks to Qiskit Aer. The results are stored in a dictionary that gather the counts obtained for all possible bitstrings.

Parameters:
  • exp_env (ExperimentalEnvironment | None) – Noise environment from which time traces are drawn. If None, a single deterministic evaluation is performed.

  • simulator (-) – an instance of qiksit’s AerSimulator.

Returns:

A dictionary which keys are the obtained bitstrings and their respective number of occurences.

Return type:

dict

fidelity(circ_ref=None)[source]

Compute the average gate fidelity with respect to a reference circuit.

The PulseCircuit is converted to a qiskit.QuantumCircuit, and the average gate fidelity between its unitary and that of the reference circuit is computed using the qiskit.quantum_info.Operator representation.

Parameters:

circ_ref (qiskit.QuantumCircuit) – Reference circuit used to define the target unitary. Default is self.original_circ

Returns:

Average gate fidelity between the PulseCircuit unitary and the reference circuit unitary.

Return type:

float

mean_fidelity(exp_env, circ_ref=None)[source]

Estimate the mean fidelity under a stochastic noise environment.

The average gate fidelity with respect to a reference circuit is computed for multiple noise realizations drawn from the experimental environment, and the results are averaged using averaging_over_samples.

Parameters:
  • circ_ref (qiskit.QuantumCircuit) – Reference circuit used to define the target unitary.

  • exp_env (ExperimentalEnvironment | None) – Noise environment from which time traces are drawn.

Returns:

Sample-averaged gate fidelity under the specified noise model.

Return type:

float

mean_channel(exp_env=None)[source]

Estimate the mean quantum channel generated by the pulse circuit.

For each noise realization, the PulseCircuit is converted to a qiskit.QuantumCircuit and then to a SuperOp representing the corresponding quantum channel. The channels are averaged over samples using averaging_over_samples.

Parameters:

exp_env (ExperimentalEnvironment | None) – Noise environment from which time traces are drawn.

Returns:

Sample-averaged quantum channel acting on the qubit register.

Return type:

qiskit.quantum_info.SuperOp

attach_time_traces(exp_env=None)[source]

Attach noise time traces from the experimental environment to the pulse circuit.

If an experimental environment is provided, this method extracts segments of the environment time traces that match the total circuit duration and assigns them to the PulseCircuit and each PulseLayer. For one-qubit pulse sequences, the corresponding single-qubit time traces are attached (qubit’s frequency deviation). For two-qubit sequences, coupling time traces are attached if available (i.e. J coupling noise) and used to set the J noise deviation during two-qubit gates.

The internal laboratory time pointer t_lab is incremented by the circuit duration after attaching the time traces, so that subsequent calls use the next segment of the noise time trace.

Parameters:

exp_env (ExperimentalEnvironment | None) – Experimental environment providing qubit’s frequency deviation time trace and, optionally, J coupling deviation time traces. If None, no trace is attached.

attach_dynamical_decoupling(hardware_specs)[source]

Insert dynamical decoupling sequences into all pulse layers, when possible (i.e. Idle time sufficiently long).

If a dynamical decoupling mode is specified in the hardware specifications, each PulseLayer in the circuit is updated by calling its attach_dynamical_decoupling method with the chosen mode. If no dynamical decoupling is configured, the circuit is left unchanged.

Parameters:

hardware_specs (HardwareSpecs) – Hardware configuration specifying the dynamical decoupling mode and available pulse shapes.