Skip to main content

cqlib_core/device/
qubit.rs

1// This code is part of Cqlib.
2//
3// (C) Copyright China Telecom Quantum Group 2026
4//
5// This code is licensed under the Apache License, Version 2.0. You may
6// obtain a copy of this license in the LICENSE.txt file in the root directory
7// of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
8//
9// Any modifications or derivative works of this code must retain this
10// copyright notice, and modified files need to carry a notice indicating
11// that they have been altered from the originals.
12
13//! Strongly typed qubit identifiers for device-facing APIs.
14//!
15//! Circuit operations use [`Qubit`] as logical wire identifiers. Device-facing
16//! code must distinguish those logical identifiers from physical hardware
17//! positions. [`LogicalQubit`] and [`PhysicalQubit`] provide that distinction
18//! without changing the compact representation.
19
20use crate::circuit::Qubit;
21use std::fmt;
22
23/// Logical qubit identifier used when crossing into device-facing code.
24///
25/// A logical qubit identifies a circuit wire. It is distinct from a
26/// [`PhysicalQubit`], even when both carry the same numeric identifier.
27#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
28#[repr(transparent)]
29pub struct LogicalQubit(Qubit);
30
31impl LogicalQubit {
32    /// Creates a logical qubit identifier from its numeric ID.
33    #[inline]
34    pub const fn new(id: u32) -> Self {
35        Self(Qubit::new(id))
36    }
37
38    /// Wraps an existing circuit qubit as a logical qubit identifier.
39    #[inline]
40    pub const fn from_qubit(qubit: Qubit) -> Self {
41        Self(qubit)
42    }
43
44    /// Returns the underlying circuit qubit identifier.
45    #[inline]
46    pub const fn qubit(self) -> Qubit {
47        self.0
48    }
49
50    /// Returns the numeric qubit identifier.
51    #[inline]
52    pub const fn id(self) -> u32 {
53        self.0.id()
54    }
55}
56
57impl From<Qubit> for LogicalQubit {
58    fn from(qubit: Qubit) -> Self {
59        Self::from_qubit(qubit)
60    }
61}
62
63impl From<LogicalQubit> for Qubit {
64    fn from(qubit: LogicalQubit) -> Self {
65        qubit.qubit()
66    }
67}
68
69impl fmt::Display for LogicalQubit {
70    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71        write!(f, "L{}", self.id())
72    }
73}
74
75/// Physical qubit identifier representing a hardware position on a device.
76///
77/// A physical qubit is not a circuit wire. Layout code is responsible for
78/// mapping [`LogicalQubit`] values to physical qubits.
79#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
80#[repr(transparent)]
81pub struct PhysicalQubit(Qubit);
82
83impl PhysicalQubit {
84    /// Creates a physical qubit identifier from its numeric ID.
85    #[inline]
86    pub const fn new(id: u32) -> Self {
87        Self(Qubit::new(id))
88    }
89
90    /// Wraps an existing qubit-shaped identifier as a physical hardware ID.
91    #[inline]
92    pub const fn from_qubit(qubit: Qubit) -> Self {
93        Self(qubit)
94    }
95
96    /// Returns the underlying qubit-shaped identifier.
97    #[inline]
98    pub const fn qubit(self) -> Qubit {
99        self.0
100    }
101
102    /// Returns the numeric hardware-qubit identifier.
103    #[inline]
104    pub const fn id(self) -> u32 {
105        self.0.id()
106    }
107}
108
109impl From<Qubit> for PhysicalQubit {
110    fn from(qubit: Qubit) -> Self {
111        Self::from_qubit(qubit)
112    }
113}
114
115impl From<PhysicalQubit> for Qubit {
116    fn from(qubit: PhysicalQubit) -> Self {
117        qubit.qubit()
118    }
119}
120
121impl fmt::Display for PhysicalQubit {
122    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
123        write!(f, "P{}", self.id())
124    }
125}