Source code for spin_pulse.environment.experimental_environment

# --------------------------------------------------------------------------------------
# This code is part of SpinPulse.
#
# (C) Copyright Quobly 2025.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
# --------------------------------------------------------------------------------------
"""Description of the noisy environment associated to a hardware."""

from ..transpilation.hardware_specs import HardwareSpecs
from .noise import (
    NoiseType,
    PinkNoiseTimeTrace,
    QuasistaticNoiseTimeTrace,
    WhiteNoiseTimeTrace,
)


[docs] class ExperimentalEnvironment: """ Contain a quantum experimental environment with configurable noise models. Attributes: - 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 without noise on the qubit's frequency. - duration (int): Total duration of the simulation. - segment_duration (int): Duration of each noise segment; used to partition the time trace. - only_idle (bool): Flag to apply noise only to idle qubits. - time_traces (list[float]): List of time traces for each qubit. - time_traces_coupling (list[float]): List of time traces for coupling noise for each pair of qubits (if TJS is set). - seed (int or None): seed integer for random number generation. If not specified, no seed used. """ # noise_generator (class): Noise generator class based on noise_type. :no-index:
[docs] noise_generator: ( type[WhiteNoiseTimeTrace] | type[QuasistaticNoiseTimeTrace] | type[PinkNoiseTimeTrace] )
def __init__( self, hardware_specs: HardwareSpecs, noise_type: NoiseType = NoiseType.PINK, T2S: float = 100.0, TJS: float | None = None, duration: int = 2**10, only_idle: bool = False, segment_duration: int = 2**10, seed: int | None = 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. """
[docs] self.hardware_specs: HardwareSpecs = hardware_specs
[docs] self.noise_type: NoiseType = noise_type
[docs] self.T2S: float = T2S
[docs] self.TJS: float | None = TJS
[docs] self.duration: int = duration
[docs] self.segment_duration: int = segment_duration
[docs] self.seed: int | None = seed
match noise_type: case NoiseType.PINK: self.noise_generator = PinkNoiseTimeTrace case NoiseType.WHITE: self.noise_generator = WhiteNoiseTimeTrace case NoiseType.QUASISTATIC: self.noise_generator = QuasistaticNoiseTimeTrace case _: raise ValueError("unknown noise type")
[docs] self.only_idle = only_idle
self.generate_time_traces()
[docs] def generate_time_traces(self): """ 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). """ self.time_traces = [] for _ in range(self.hardware_specs.num_qubits): time_trace = self.noise_generator( self.T2S, self.duration, self.segment_duration, seed=self.seed ) self.time_traces.append(time_trace) if self.TJS is not None: self.time_traces_coupling = [] for _ in range(self.hardware_specs.num_qubits - 1): time_trace = self.noise_generator( self.TJS, self.duration, self.segment_duration, seed=self.seed ) self.time_traces_coupling.append(time_trace)
def __str__(self): """ Return a string representation of the ExperimentalEnvironment instance. Includes: Number of qubits Noise type T2S and TJS values Duration and segment duration Whether noise is only appplied to idle qubits The J coupling value set in HardwareSpecs The total number of generated time traces The total number of generated coupling time traces if there exists some """ summary = [ "ExperimentalEnvironment:", f" Qubits: {self.hardware_specs.num_qubits}", f" Noise Type: {self.noise_type}", f" T2S (qubit dephasing): {self.T2S}", f" TJS (coupling dephasing): {self.TJS if self.TJS is not None else 'None'}", f" Duration: {self.duration}", f" Segment Duration: {self.segment_duration}", f" Only Idle: {self.only_idle}", f" J Coupling: {self.hardware_specs.J_coupling if self.hardware_specs.J_coupling is not None else 'None'}", f" Time Traces Generated: {len(self.time_traces)}", f" Seed: {self.seed}", ] if hasattr(self, "time_traces_coupling"): summary.append( f" Coupling Time Traces Generated: {len(self.time_traces_coupling)}" ) return "\n".join(summary)