Skip to main content

quantrs2_core/
qubit.rs

1//! Qubit identifier types for type-safe quantum circuit construction.
2//!
3//! Provides [`QubitId`], a zero-cost transparent wrapper around a `u32` that
4//! uniquely identifies a qubit within a circuit or register.
5
6use serde::{Deserialize, Serialize};
7
8/// A transparent wrapper around a qubit identifier.
9///
10/// This provides type safety for qubit references while
11/// maintaining zero-cost abstraction.
12///
13/// # Examples
14///
15/// ```rust
16/// use quantrs2_core::qubit::QubitId;
17///
18/// let q0 = QubitId::new(0);
19/// let q1 = QubitId::new(1);
20/// assert_eq!(q0.id(), 0);
21/// assert!(q0 < q1);
22/// ```
23#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
24#[repr(transparent)]
25pub struct QubitId(pub u32);
26
27impl QubitId {
28    /// Create a new qubit identifier.
29    ///
30    /// # Examples
31    ///
32    /// ```rust
33    /// use quantrs2_core::qubit::QubitId;
34    /// let q = QubitId::new(3);
35    /// assert_eq!(q.id(), 3);
36    /// ```
37    #[inline]
38    pub const fn new(id: u32) -> Self {
39        Self(id)
40    }
41
42    /// Get the raw identifier value.
43    #[inline]
44    pub const fn id(&self) -> u32 {
45        self.0
46    }
47}
48
49impl From<u32> for QubitId {
50    #[inline]
51    fn from(id: u32) -> Self {
52        Self(id)
53    }
54}
55
56impl From<QubitId> for u32 {
57    #[inline]
58    fn from(qubit: QubitId) -> Self {
59        qubit.0
60    }
61}
62
63impl From<usize> for QubitId {
64    #[inline]
65    fn from(id: usize) -> Self {
66        Self(id as u32)
67    }
68}
69
70impl From<QubitId> for usize {
71    #[inline]
72    fn from(qubit: QubitId) -> Self {
73        qubit.0 as Self
74    }
75}
76
77impl From<i32> for QubitId {
78    #[inline]
79    fn from(id: i32) -> Self {
80        Self(id as u32)
81    }
82}
83
84/// A collection of qubits for multi-qubit operations
85#[derive(Debug, Clone, PartialEq, Eq)]
86pub struct QubitSet {
87    qubits: Vec<QubitId>,
88}
89
90impl QubitSet {
91    /// Create a new empty qubit set
92    pub const fn new() -> Self {
93        Self { qubits: Vec::new() }
94    }
95
96    /// Create a qubit set with a specific capacity
97    pub fn with_capacity(capacity: usize) -> Self {
98        Self {
99            qubits: Vec::with_capacity(capacity),
100        }
101    }
102
103    /// Add a qubit to the set
104    pub fn add(&mut self, qubit: impl Into<QubitId>) {
105        self.qubits.push(qubit.into());
106    }
107
108    /// Get all qubits in the set
109    pub fn qubits(&self) -> &[QubitId] {
110        &self.qubits
111    }
112
113    /// Get the number of qubits in the set
114    pub fn len(&self) -> usize {
115        self.qubits.len()
116    }
117
118    /// Check if the set is empty
119    pub fn is_empty(&self) -> bool {
120        self.qubits.is_empty()
121    }
122}
123
124impl Default for QubitSet {
125    fn default() -> Self {
126        Self::new()
127    }
128}
129
130impl From<Vec<QubitId>> for QubitSet {
131    fn from(qubits: Vec<QubitId>) -> Self {
132        Self { qubits }
133    }
134}
135
136impl<const N: usize> From<[QubitId; N]> for QubitSet {
137    fn from(qubits: [QubitId; N]) -> Self {
138        Self {
139            qubits: qubits.to_vec(),
140        }
141    }
142}
143
144impl<const N: usize> From<[u32; N]> for QubitSet {
145    fn from(ids: [u32; N]) -> Self {
146        let qubits = ids.iter().map(|&id| QubitId::new(id)).collect();
147        Self { qubits }
148    }
149}