Qubit

Struct Qubit 

Source
#[repr(transparent)]
pub struct Qubit(pub u32);
Expand description

A transparent wrapper around a qubit identifier

This provides type safety for qubit references while maintaining zero-cost abstraction.

Tuple Fields§

§0: u32

Implementations§

Source§

impl QubitId

Source

pub const fn new(id: u32) -> QubitId

Create a new qubit identifier

Examples found in repository?
examples/qasm_example.rs (line 31)
23fn export_example() {
24    println!("1. Exporting a circuit to OpenQASM 3.0");
25    println!("--------------------------------------");
26
27    // Create a quantum teleportation circuit
28    let mut builder = CircuitBuilder::<3>::new();
29
30    // Create Bell pair between Alice and Bob
31    let _ = builder.h(Qubit::new(1));
32    let _ = builder.cx(Qubit::new(1), Qubit::new(2));
33
34    // Alice's operations
35    let _ = builder.cx(Qubit::new(0), Qubit::new(1));
36    let _ = builder.h(Qubit::new(0));
37
38    // Measurements (in real teleportation, these would be mid-circuit)
39    let _ = builder.measure(Qubit::new(0));
40    let _ = builder.measure(Qubit::new(1));
41
42    // Bob's corrections (would be conditional in real circuit)
43    let _ = builder.cx(Qubit::new(1), Qubit::new(2));
44    let _ = builder.cz(Qubit::new(0), Qubit::new(2));
45
46    let circuit = builder.build();
47
48    // Export with default options
49    match export_qasm3(&circuit) {
50        Ok(qasm) => {
51            println!("Teleportation circuit in OpenQASM 3.0:");
52            println!("{}", qasm);
53        }
54        Err(e) => println!("Export error: {}", e),
55    }
56
57    // Export with custom options
58    let options = ExportOptions {
59        include_stdgates: true,
60        decompose_custom: true,
61        include_gate_comments: true,
62        optimize: true,
63        pretty_print: true,
64    };
65
66    let mut exporter = QasmExporter::new(options);
67    match exporter.export(&circuit) {
68        Ok(qasm) => {
69            println!("\nWith custom options:");
70            println!("{}", qasm);
71        }
72        Err(e) => println!("Export error: {}", e),
73    }
74}
75
76fn parse_example() {
77    println!("\n2. Parsing OpenQASM 3.0 code");
78    println!("----------------------------");
79
80    let qasm_code = r#"
81OPENQASM 3.0;
82include "stdgates.inc";
83
84// Quantum registers
85qubit[5] q;
86bit[5] c;
87
88// Create W state
89reset q;
90ry(1.91063) q[0];  // arccos(1/sqrt(5))
91cx q[0], q[1];
92
93// Controlled rotations to distribute amplitude
94cry(1.10715) q[1], q[2];  // arccos(1/2)
95cx q[1], q[2];
96
97cry(0.95532) q[2], q[3];  // arccos(1/sqrt(3))
98cx q[2], q[3];
99
100cry(pi/4) q[3], q[4];
101cx q[3], q[4];
102
103// Measure all qubits
104measure q -> c;
105"#;
106
107    match parse_qasm3(qasm_code) {
108        Ok(program) => {
109            println!("Successfully parsed QASM program!");
110            println!("Version: {}", program.version);
111            println!("Includes: {:?}", program.includes);
112            println!("Declarations: {} items", program.declarations.len());
113            println!("Statements: {} operations", program.statements.len());
114
115            // Pretty print the parsed program
116            println!("\nReconstructed QASM:");
117            println!("{}", program);
118        }
119        Err(e) => println!("Parse error: {}", e),
120    }
121}
122
123fn validation_example() {
124    println!("\n3. Validating QASM programs");
125    println!("---------------------------");
126
127    // Valid program
128    let valid_qasm = r#"
129OPENQASM 3.0;
130
131gate mybell a, b {
132    h a;
133    cx a, b;
134}
135
136qubit[4] q;
137bit[2] c;
138
139mybell q[0], q[1];
140mybell q[2], q[3];
141
142measure q[0] -> c[0];
143measure q[2] -> c[1];
144"#;
145
146    println!("Validating correct program...");
147    match parse_qasm3(valid_qasm) {
148        Ok(program) => match validate_qasm3(&program) {
149            Ok(()) => println!("✓ Program is valid!"),
150            Err(e) => println!("✗ Validation error: {}", e),
151        },
152        Err(e) => println!("Parse error: {}", e),
153    }
154
155    // Program with errors
156    let invalid_qasm = r#"
157OPENQASM 3.0;
158
159qubit[2] q;
160bit[2] c;
161
162// Error: using undefined register
163h r[0];
164
165// Error: index out of bounds
166cx q[0], q[5];
167
168// Error: wrong number of parameters
169rx q[0];  // Missing angle parameter
170"#;
171
172    println!("\nValidating program with errors...");
173    match parse_qasm3(invalid_qasm) {
174        Ok(program) => match validate_qasm3(&program) {
175            Ok(()) => println!("Program is valid (unexpected!)"),
176            Err(e) => println!("✓ Caught validation error: {}", e),
177        },
178        Err(e) => println!("Parse error: {}", e),
179    }
180}
181
182fn round_trip_example() {
183    println!("\n4. Round-trip conversion");
184    println!("------------------------");
185
186    // Create a variational circuit
187    let mut builder = CircuitBuilder::<4>::new();
188
189    // Layer 1: Single-qubit rotations
190    for i in 0..4 {
191        let _ = builder.ry(Qubit::new(i), 0.5);
192        let _ = builder.rz(Qubit::new(i), 0.3);
193    }
194
195    // Layer 2: Entangling gates
196    for i in 0..3 {
197        let _ = builder.cx(Qubit::new(i), Qubit::new(i + 1));
198    }
199    let _ = builder.cx(Qubit::new(3), Qubit::new(0)); // Circular connectivity
200
201    // Layer 3: More rotations
202    for i in 0..4 {
203        let _ = builder.rx(Qubit::new(i), -0.2);
204    }
205
206    // Measurements
207    for i in 0..4 {
208        let _ = builder.measure(Qubit::new(i));
209    }
210
211    let original = builder.build();
212
213    println!(
214        "Original circuit created with {} gates",
215        original.gates().len()
216    );
217
218    // Export to QASM
219    match export_qasm3(&original) {
220        Ok(qasm) => {
221            println!("\nExported QASM:");
222            println!("{}", qasm);
223
224            // Parse it back
225            match parse_qasm3(&qasm) {
226                Ok(program) => {
227                    println!("\n✓ Successfully parsed the exported QASM!");
228
229                    // Validate it
230                    match validate_qasm3(&program) {
231                        Ok(()) => println!("✓ Validation passed!"),
232                        Err(e) => println!("✗ Validation error: {}", e),
233                    }
234
235                    // Count operations
236                    let gate_count = program
237                        .statements
238                        .iter()
239                        .filter(|s| {
240                            matches!(s, quantrs2_circuit::qasm::ast::QasmStatement::Gate(_))
241                        })
242                        .count();
243                    let measure_count = program
244                        .statements
245                        .iter()
246                        .filter(|s| {
247                            matches!(s, quantrs2_circuit::qasm::ast::QasmStatement::Measure(_))
248                        })
249                        .count();
250
251                    println!("\nParsed circuit has:");
252                    println!("  - {} gate operations", gate_count);
253                    println!("  - {} measurements", measure_count);
254                }
255                Err(e) => println!("Parse error: {}", e),
256            }
257        }
258        Err(e) => println!("Export error: {}", e),
259    }
260}
Source

pub const fn id(&self) -> u32

Get the raw identifier value

Examples found in repository?
examples/crosstalk_demo.rs (line 374)
325fn demo_adaptive_scheduling() -> quantrs2_core::error::QuantRS2Result<()> {
326    println!("--- Adaptive Scheduling ---");
327
328    // Create a circuit with varying gate densities
329    let mut circuit = Circuit::<8>::new();
330
331    // Dense region: many gates on qubits 0-3
332    for _ in 0..3 {
333        for i in 0..3 {
334            circuit.add_gate(Hadamard { target: QubitId(i) })?;
335            circuit.add_gate(RotationZ {
336                target: QubitId(i),
337                theta: 0.1,
338            })?;
339        }
340        circuit.add_gate(CNOT {
341            control: QubitId(0),
342            target: QubitId(1),
343        })?;
344        circuit.add_gate(CNOT {
345            control: QubitId(2),
346            target: QubitId(3),
347        })?;
348    }
349
350    // Sparse region: few gates on qubits 4-7
351    circuit.add_gate(Hadamard { target: QubitId(4) })?;
352    circuit.add_gate(CNOT {
353        control: QubitId(4),
354        target: QubitId(5),
355    })?;
356    circuit.add_gate(PauliX { target: QubitId(7) })?;
357
358    println!("Circuit with dense (qubits 0-3) and sparse (qubits 4-7) regions");
359    println!("Total gates: {}", circuit.num_gates());
360
361    let model = CrosstalkModel::uniform(8, 0.05);
362    let analyzer = CrosstalkAnalyzer::new(model.clone());
363
364    // Analyze before scheduling
365    let analysis = analyzer.analyze(&circuit);
366    println!("\nCrosstalk analysis:");
367    println!(
368        "  Problematic pairs in dense region: {}",
369        analysis
370            .problematic_pairs
371            .iter()
372            .filter(|(g1, g2, _)| {
373                let gates = circuit.gates();
374                let q1 = gates[*g1].qubits()[0].id();
375                let q2 = gates[*g2].qubits()[0].id();
376                q1 < 4 && q2 < 4
377            })
378            .count()
379    );
380
381    // Schedule with adaptive strategy
382    let scheduler = CrosstalkScheduler::new(model);
383    let schedule = scheduler.schedule(&circuit)?;
384
385    println!("\nAdaptive scheduling results:");
386    println!("  Time slices: {}", schedule.time_slices.len());
387    println!(
388        "  Average gates per slice: {:.1}",
389        circuit.num_gates() as f64 / schedule.time_slices.len() as f64
390    );
391
392    Ok(())
393}

Trait Implementations§

Source§

impl Clone for QubitId

Source§

fn clone(&self) -> QubitId

Returns a duplicate of the value. Read more
1.0.0 · Source§

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

Performs copy-assignment from source. Read more
Source§

impl Debug for QubitId

Source§

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

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for QubitId

Source§

fn deserialize<__D>( __deserializer: __D, ) -> Result<QubitId, <__D as Deserializer<'de>>::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl From<QubitId> for u32

Source§

fn from(qubit: QubitId) -> u32

Converts to this type from the input type.
Source§

impl From<i32> for QubitId

Source§

fn from(id: i32) -> QubitId

Converts to this type from the input type.
Source§

impl From<u32> for QubitId

Source§

fn from(id: u32) -> QubitId

Converts to this type from the input type.
Source§

impl From<usize> for QubitId

Source§

fn from(id: usize) -> QubitId

Converts to this type from the input type.
Source§

impl Hash for QubitId

Source§

fn hash<__H>(&self, state: &mut __H)
where __H: Hasher,

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl Ord for QubitId

Source§

fn cmp(&self, other: &QubitId) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · Source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · Source§

fn min(self, other: Self) -> Self
where Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 · Source§

fn clamp(self, min: Self, max: Self) -> Self
where Self: Sized,

Restrict a value to a certain interval. Read more
Source§

impl PartialEq for QubitId

Source§

fn eq(&self, other: &QubitId) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl PartialOrd for QubitId

Source§

fn partial_cmp(&self, other: &QubitId) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · Source§

fn lt(&self, other: &Rhs) -> bool

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · Source§

fn le(&self, other: &Rhs) -> bool

Tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 · Source§

fn gt(&self, other: &Rhs) -> bool

Tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · Source§

fn ge(&self, other: &Rhs) -> bool

Tests greater than or equal to (for self and other) and is used by the >= operator. Read more
Source§

impl Serialize for QubitId

Source§

fn serialize<__S>( &self, __serializer: __S, ) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl Copy for QubitId

Source§

impl Eq for QubitId

Source§

impl StructuralPartialEq for QubitId

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> 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<Q, K> Comparable<K> for Q
where Q: Ord + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn compare(&self, key: &K) -> Ordering

Compare self to key and return their ordering.
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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> 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> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<SS, SP> SupersetOf<SS> for SP
where SS: SubsetOf<SP>,

Source§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its superset. Read more
Source§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
Source§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
Source§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
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, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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

Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<N> NodeTrait for N
where N: Copy + Ord + Hash,

Source§

impl<T> RuleType for T
where T: Copy + Debug + Eq + Hash + Ord,

Source§

impl<T> Scalar for T
where T: 'static + Clone + PartialEq + Debug,

Source§

impl<T> Ungil for T
where T: Send,