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}