Skip to main content

Device

Struct Device 

Source
pub struct Device { /* private fields */ }
Expand description

Represents a quantum device’s hardware characteristics and topology.

The Device struct is a fundamental component for compiler optimization, mapping, routing, and noise-aware scheduling. It encapsulates:

  • The physical connectivity (Topology) between qubits.
  • Available and faulty qubits.
  • Device-wide default parameters (e.g., T1, T2, gate error rates).
  • Specific physical properties and supported instructions for individual qubits and coupling edges.

This structure provides the necessary physical constraints and fidelity data required to simulate noise models or compile quantum circuits onto realistic backend hardware.

§Example

use std::collections::HashSet;
use cqlib_core::device::{Device, PhysicalQubit, QubitProp, Topology};

// Create a 2-qubit topology
let q0 = PhysicalQubit::new(0);
let q1 = PhysicalQubit::new(1);
let topo = Topology::new(vec![q0, q1], vec![(q0, q1, "G1".to_string())]).unwrap();

// Initialize a device with defaults
let mut device = Device::new("mock_device", HashSet::from_iter([q0, q1]), topo).unwrap()
    .with_default_t1(50.0)
    .with_default_t2(25.0)
    .with_default_readout_error(0.01);

// Add specific properties for Qubit 0
let q0_prop = QubitProp::new(0.05).with_t1(40.0);
device.add_qubit_properties(q0, q0_prop).unwrap();

// Query T1, using specific properties if available, else fallback to defaults
assert_eq!(device.get_t1(q0), Some(40.0));
assert_eq!(device.get_t1(q1), Some(50.0));

Implementations§

Source§

impl Device

Source

pub fn new( name: impl Into<String>, qubits: HashSet<PhysicalQubit>, topology: Topology, ) -> Result<Self, DeviceError>

Creates a new Device with the specified name and topology.

Source

pub fn line( name: impl Into<String>, num_qubits: u32, ) -> Result<Self, DeviceError>

Creates a device with physical qubits connected as a directed line.

The device contains physical qubits 0..num_qubits, all of which are online. Native gates and calibration data are left unset and may be configured with the builder-style setters.

Source

pub fn line_from_qubits( name: impl Into<String>, physical_qubits: Vec<PhysicalQubit>, ) -> Result<Self, DeviceError>

Creates a device with the supplied physical qubits connected as a directed line.

The device contains every supplied physical qubit, all of which are online. Couplings follow the supplied order: qubits[i] -> qubits[i + 1].

§Errors

Returns DeviceError::EmptyDevice if physical_qubits is empty.

Source

pub fn bidirectional_line( name: impl Into<String>, num_qubits: u32, ) -> Result<Self, DeviceError>

Creates a device with physical qubits connected as a bidirectional line.

The device contains physical qubits 0..num_qubits, all of which are online. Adjacent qubits are connected in both directions.

Source

pub fn ring( name: impl Into<String>, num_qubits: u32, ) -> Result<Self, DeviceError>

Creates a device with physical qubits connected as a bidirectional ring.

The device contains physical qubits 0..num_qubits, all of which are online. For two or more qubits, each qubit is connected to its successor modulo num_qubits in both directions.

Source

pub fn star( name: impl Into<String>, num_qubits: u32, center: u32, ) -> Result<Self, DeviceError>

Creates a device with physical qubits connected as a bidirectional star.

The device contains physical qubits 0..num_qubits, all of which are online. Every non-center qubit is connected to center in both directions.

Source

pub fn grid( name: impl Into<String>, rows: u32, cols: u32, ) -> Result<Self, DeviceError>

Creates a device with physical qubits connected as a bidirectional grid.

Qubit IDs are assigned in row-major order. Horizontal and vertical nearest-neighbor couplings are added in both directions.

Source

pub fn from_edges( name: impl Into<String>, num_qubits: u32, edges: &[(u32, u32)], ) -> Result<Self, DeviceError>

Creates a device with physical qubits 0..num_qubits and explicit directed edges.

Each (control, target) pair in edges becomes one directed coupling.

Source

pub fn with_invalid_qubits( self, invalid_qubits: HashSet<PhysicalQubit>, ) -> Result<Self, DeviceError>

Sets the offline or faulty physical qubits using the builder pattern.

§Errors

Returns DeviceError::QubitNotInDevice if any invalid qubit is not registered with the device.

Source

pub fn set_invalid_qubits( &mut self, invalid_qubits: HashSet<PhysicalQubit>, ) -> Result<(), DeviceError>

Sets the offline or faulty physical qubits.

§Errors

Returns DeviceError::QubitNotInDevice if any invalid qubit is not registered with the device. The existing set is preserved on error.

Source

pub fn with_native_gates( self, gates: Vec<Instruction>, ) -> Result<Self, DeviceError>

Sets the device-wide default native gates.

This does not add, remove, or otherwise synchronize native instructions stored on individual qubits or directed edges.

§Errors

Returns DeviceError if any entry is not a standard gate or acts on more than two qubits.

Source

pub fn set_native_gates( &mut self, gates: Vec<Instruction>, ) -> Result<(), DeviceError>

Replaces the device-wide native defaults after validating the full list.

The existing defaults are preserved when any entry is invalid.

§Errors

Returns DeviceError if any entry is not a standard gate or acts on more than two qubits.

Source

pub fn with_calibration_time(self, time: OffsetDateTime) -> Self

Sets the system calibration timestamp.

Source

pub fn set_calibration_time(&mut self, time: OffsetDateTime)

Source

pub fn with_default_t1(self, t1: f64) -> Self

Sets the default T1 time (μs).

Source

pub fn set_default_t1(&mut self, t1: f64)

Source

pub fn with_default_t2(self, t2: f64) -> Self

Sets the default T2 time (μs).

Source

pub fn set_default_t2(&mut self, t2: f64)

Source

pub fn with_default_readout_error(self, error: f64) -> Self

Sets the default readout error rate.

Source

pub fn set_default_readout_error(&mut self, error: f64)

Source

pub fn with_default_single_qubit_error(self, error: f64) -> Self

Sets the default single-qubit gate error rate.

Source

pub fn set_default_single_qubit_error(&mut self, error: f64)

Source

pub fn with_default_two_qubit_error(self, error: f64) -> Self

Sets the default two-qubit gate error rate.

Source

pub fn set_default_two_qubit_error(&mut self, error: f64)

Source

pub fn add_qubit_properties( &mut self, qubit: PhysicalQubit, props: QubitProp, ) -> Result<(), DeviceError>

Adds properties for a specific qubit.

§Errors

Returns DeviceError::QubitNotInDevice if the qubit is not registered with the device, or DeviceError::QubitNotInTopology if it is registered but absent from the topology. Properties may be retained for a registered qubit while it is marked invalid/offline.

Source

pub fn add_edge_properties( &mut self, control: PhysicalQubit, target: PhysicalQubit, props: EdgeProp, ) -> Result<(), DeviceError>

Adds properties for a specific coupling edge.

§Errors

Returns DeviceError::EdgeNotInTopology if the edge is not in the device’s topology.

Source

pub fn name(&self) -> &str

Gets the name of the device.

Source

pub fn qubits(&self) -> impl Iterator<Item = PhysicalQubit> + '_

Gets an iterator over the physical qubits registered with the device.

Source

pub fn invalid_qubits(&self) -> impl Iterator<Item = PhysicalQubit> + '_

Gets an iterator over the invalid (offline/faulty) qubits.

Source

pub fn is_usable_qubit(&self, qubit: PhysicalQubit) -> bool

Returns whether a physical qubit is registered and not marked invalid.

Source

pub fn usable_qubits(&self) -> impl Iterator<Item = PhysicalQubit> + '_

Gets an iterator over registered physical qubits that are not invalid.

Source

pub fn num_usable_qubits(&self) -> usize

Returns the number of registered physical qubits that are not invalid.

Source

pub fn topology(&self) -> &Topology

Gets a reference to the device’s connectivity topology.

Source

pub fn native_gates(&self) -> &[Instruction]

Gets the default native gates supported by the device.

Source

pub fn qubit_properties(&self, qubit: PhysicalQubit) -> Option<&QubitProp>

Gets the properties of a specific qubit.

Source

pub fn edge_properties( &self, control: PhysicalQubit, target: PhysicalQubit, ) -> Option<&EdgeProp>

Gets the properties of a specific coupling edge.

Source

pub fn supports_native_instruction( &self, instruction: &Instruction, qargs: &[PhysicalQubit], ) -> bool

Returns whether a native hardware instruction can execute on the exact ordered physical qargs.

This query evaluates capability only; calibration error rates and durations do not affect the result. Standard one- and two-qubit gates follow the device default/local-override contract, and two-qubit qargs are directional. Structured control flow, runtime operations, and composite gates are not atomic device capabilities; validate them with Self::validate_operation or Self::validate_circuit instead.

Source

pub fn validate_operation( &self, operation: &Operation, ) -> Result<(), DeviceValidationError>

Validates one operation interpreted in the physical-qubit ID space.

Structured control-flow bodies are checked recursively. This method is read-only and never performs layout, routing, lowering, or direction correction.

Source

pub fn validate_value_operation( &self, operation: &ValueOperation, ) -> Result<(), DeviceValidationError>

Validates one value-level operation interpreted in the physical-qubit ID space.

This is the construction-IR counterpart of Self::validate_operation. Structured control-flow bodies are checked recursively without first converting the operation into a Circuit, so circuit-owned classical variables and values are not required solely for device validation.

Source

pub fn validate_circuit( &self, circuit: &Circuit, ) -> Result<(), DeviceValidationError>

Validates a circuit interpreted in the physical-qubit ID space.

Validation stops at the first unsupported operation. The circuit is not modified and must already have completed logical-to-physical mapping and hardware lowering.

Source

pub fn single_qubit_error( &self, qubit: PhysicalQubit, instruction: &Instruction, ) -> Option<f64>

Gets the error rate for instruction on a single physical qubit.

Returns None if the qubit is not usable or does not support the instruction. A non-empty local native-instruction list is a complete capability override; otherwise device-wide one-qubit defaults apply. The default error rate is used only for an inherited supported gate.

Source

pub fn two_qubit_error( &self, control: PhysicalQubit, target: PhysicalQubit, instruction: &Instruction, ) -> Option<f64>

Gets the error rate for instruction on a directed coupling.

Returns None if either endpoint is not usable, the exact directed coupling does not exist, or that edge does not support the instruction. A non-empty local native-instruction list is a complete capability override; otherwise device-wide two-qubit defaults apply. The default error rate is used only for an inherited supported gate.

Source

pub fn edge_error( &self, control: PhysicalQubit, target: PhysicalQubit, ) -> Option<f64>

Gets a direction-specific coupling error suitable for routing costs.

Returns the best available native two-qubit instruction error on the edge, or the default two-qubit error if no per-edge calibration exists.

This instruction-agnostic calibration query does not prove that any two-qubit instruction is supported, even when it returns Some. It must not be used as a capability predicate. Use Self::supports_native_instruction or Self::two_qubit_error when a concrete instruction capability matters.

Source

pub fn get_t1(&self, qubit: PhysicalQubit) -> Option<f64>

Gets the T1 relaxation time for a qubit (μs).

Falls back to the default T1 time if not specified for the qubit.

Source

pub fn get_t2(&self, qubit: PhysicalQubit) -> Option<f64>

Gets the T2 dephasing time for a qubit (μs).

Falls back to the default T2 time if not specified for the qubit.

Source

pub fn get_readout_error(&self, qubit: PhysicalQubit) -> Option<f64>

Gets the readout error rate for a qubit.

Falls back to the default readout error if not specified for the qubit.

Source

pub fn default_single_qubit_error(&self) -> Option<f64>

Gets the default single-qubit gate error rate.

Source

pub fn default_two_qubit_error(&self) -> Option<f64>

Gets the default two-qubit gate error rate.

Source

pub fn default_t1(&self) -> Option<f64>

Gets the default T1 relaxation time.

Source

pub fn default_t2(&self) -> Option<f64>

Gets the default T2 dephasing time.

Source

pub fn default_readout_error(&self) -> Option<f64>

Gets the default readout error rate.

Source

pub fn calibration_time(&self) -> Option<OffsetDateTime>

Gets the system calibration timestamp.

Trait Implementations§

Source§

impl Clone for Device

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Device

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> ByRef<T> for T

Source§

fn by_ref(&self) -> &T

Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> Conv for T

Source§

fn conv<T>(self) -> T
where Self: Into<T>,

Converts self into T using Into<T>. Read more
Source§

impl<T> DistributionExt for T
where T: ?Sized,

Source§

fn rand<T>(&self, rng: &mut (impl Rng + ?Sized)) -> T
where Self: Distribution<T>,

Source§

impl<T> FmtForward for T

Source§

fn fmt_binary(self) -> FmtBinary<Self>
where Self: Binary,

Causes self to use its Binary implementation when Debug-formatted.
Source§

fn fmt_display(self) -> FmtDisplay<Self>
where Self: Display,

Causes self to use its Display implementation when Debug-formatted.
Source§

fn fmt_lower_exp(self) -> FmtLowerExp<Self>
where Self: LowerExp,

Causes self to use its LowerExp implementation when Debug-formatted.
Source§

fn fmt_lower_hex(self) -> FmtLowerHex<Self>
where Self: LowerHex,

Causes self to use its LowerHex implementation when Debug-formatted.
Source§

fn fmt_octal(self) -> FmtOctal<Self>
where Self: Octal,

Causes self to use its Octal implementation when Debug-formatted.
Source§

fn fmt_pointer(self) -> FmtPointer<Self>
where Self: Pointer,

Causes self to use its Pointer implementation when Debug-formatted.
Source§

fn fmt_upper_exp(self) -> FmtUpperExp<Self>
where Self: UpperExp,

Causes self to use its UpperExp implementation when Debug-formatted.
Source§

fn fmt_upper_hex(self) -> FmtUpperHex<Self>
where Self: UpperHex,

Causes self to use its UpperHex implementation when Debug-formatted.
Source§

fn fmt_list(self) -> FmtList<Self>
where &'a Self: for<'a> IntoIterator,

Formats each item in a sequence. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Imply<T> for U
where T: ?Sized, U: ?Sized,

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pipe for T
where T: ?Sized,

Source§

fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
where Self: Sized,

Pipes by value. This is generally the method you want to use. Read more
Source§

fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
where R: 'a,

Borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> R
where R: 'a,

Mutably borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
where Self: Borrow<B>, B: 'a + ?Sized, R: 'a,

Borrows self, then passes self.borrow() into the pipe function. Read more
Source§

fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
where Self: BorrowMut<B>, B: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more
Source§

fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
where Self: AsRef<U>, U: 'a + ?Sized, R: 'a,

Borrows self, then passes self.as_ref() into the pipe function.
Source§

fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
where Self: AsMut<U>, U: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.as_mut() into the pipe function.
Source§

fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
where Self: Deref<Target = T>, T: 'a + ?Sized, R: 'a,

Borrows self, then passes self.deref() into the pipe function.
Source§

fn pipe_deref_mut<'a, T, R>( &'a mut self, func: impl FnOnce(&'a mut T) -> R, ) -> R
where Self: DerefMut<Target = T> + Deref, T: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.deref_mut() into the pipe function.
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Tap for T

Source§

fn tap(self, func: impl FnOnce(&Self)) -> Self

Immutable access to a value. Read more
Source§

fn tap_mut(self, func: impl FnOnce(&mut Self)) -> Self

Mutable access to a value. Read more
Source§

fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Immutable access to the Borrow<B> of a value. Read more
Source§

fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Mutable access to the BorrowMut<B> of a value. Read more
Source§

fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Immutable access to the AsRef<R> view of a value. Read more
Source§

fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Mutable access to the AsMut<R> view of a value. Read more
Source§

fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Immutable access to the Deref::Target of a value. Read more
Source§

fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Mutable access to the Deref::Target of a value. Read more
Source§

fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self

Calls .tap() only in debug builds, and is erased in release builds.
Source§

fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self

Calls .tap_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Calls .tap_borrow() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Calls .tap_borrow_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Calls .tap_ref() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Calls .tap_ref_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Calls .tap_deref() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_mut_dbg<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Calls .tap_deref_mut() only in debug builds, and is erased in release builds.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> TryConv for T

Source§

fn try_conv<T>(self) -> Result<T, Self::Error>
where Self: TryInto<T>,

Attempts to convert self into T using TryInto<T>. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V