ClassicalCircuit

Struct ClassicalCircuit 

Source
pub struct ClassicalCircuit<const N: usize> {
    pub classical_registers: HashMap<String, ClassicalRegister>,
    pub operations: Vec<CircuitOp>,
}
Expand description

A circuit with classical control flow support

Fields§

§classical_registers: HashMap<String, ClassicalRegister>

Classical registers

§operations: Vec<CircuitOp>

Operations (both quantum and classical)

Implementations§

Source§

impl<const N: usize> ClassicalCircuit<N>

Source

pub fn new() -> Self

Create a new circuit with classical control

Source

pub fn add_classical_register( &mut self, name: &str, size: usize, ) -> QuantRS2Result<()>

Add a classical register

Examples found in repository?
examples/classical_control_demo.rs (line 60)
49fn quantum_teleportation() -> Result<(), Box<dyn std::error::Error>> {
50    println!("Example 2: Quantum Teleportation");
51    println!("--------------------------------");
52
53    // Create Bell pair between qubits 1 and 2
54    let mut circuit = Circuit::<3>::new();
55    circuit.h(1)?;
56    circuit.cnot(1, 2)?;
57
58    // Convert to classical circuit for measurements
59    let mut classical_circuit = circuit.with_classical_control();
60    classical_circuit.add_classical_register("alice", 2)?;
61
62    // Alice's operations
63    classical_circuit.add_gate(quantrs2_core::gate::multi::CNOT {
64        control: QubitId(0),
65        target: QubitId(1),
66    })?;
67    classical_circuit.add_gate(Hadamard { target: QubitId(0) })?;
68
69    // Alice measures her qubits
70    classical_circuit.measure(QubitId(0), "alice", 0)?;
71    classical_circuit.measure(QubitId(1), "alice", 1)?;
72
73    // Bob applies corrections based on Alice's measurements
74    classical_circuit.add_conditional(
75        ClassicalCondition {
76            lhs: ClassicalValue::Register("alice".to_string()),
77            op: ComparisonOp::Equal,
78            rhs: ClassicalValue::Integer(0b01),
79        },
80        PauliX { target: QubitId(2) },
81    )?;
82
83    classical_circuit.add_conditional(
84        ClassicalCondition {
85            lhs: ClassicalValue::Register("alice".to_string()),
86            op: ComparisonOp::Equal,
87            rhs: ClassicalValue::Integer(0b10),
88        },
89        PauliZ { target: QubitId(2) },
90    )?;
91
92    classical_circuit.add_conditional(
93        ClassicalCondition {
94            lhs: ClassicalValue::Register("alice".to_string()),
95            op: ComparisonOp::Equal,
96            rhs: ClassicalValue::Integer(0b11),
97        },
98        PauliX { target: QubitId(2) }, // In reality, this would be X then Z
99    )?;
100
101    println!(
102        "Created teleportation circuit with {} operations",
103        classical_circuit.num_operations()
104    );
105    println!("Bob's qubit 2 receives the state that was on Alice's qubit 0\n");
106
107    Ok(())
108}
Source

pub fn add_gate<G: GateOp + 'static>(&mut self, gate: G) -> QuantRS2Result<()>

Add a quantum gate

Examples found in repository?
examples/classical_control_demo.rs (lines 63-66)
49fn quantum_teleportation() -> Result<(), Box<dyn std::error::Error>> {
50    println!("Example 2: Quantum Teleportation");
51    println!("--------------------------------");
52
53    // Create Bell pair between qubits 1 and 2
54    let mut circuit = Circuit::<3>::new();
55    circuit.h(1)?;
56    circuit.cnot(1, 2)?;
57
58    // Convert to classical circuit for measurements
59    let mut classical_circuit = circuit.with_classical_control();
60    classical_circuit.add_classical_register("alice", 2)?;
61
62    // Alice's operations
63    classical_circuit.add_gate(quantrs2_core::gate::multi::CNOT {
64        control: QubitId(0),
65        target: QubitId(1),
66    })?;
67    classical_circuit.add_gate(Hadamard { target: QubitId(0) })?;
68
69    // Alice measures her qubits
70    classical_circuit.measure(QubitId(0), "alice", 0)?;
71    classical_circuit.measure(QubitId(1), "alice", 1)?;
72
73    // Bob applies corrections based on Alice's measurements
74    classical_circuit.add_conditional(
75        ClassicalCondition {
76            lhs: ClassicalValue::Register("alice".to_string()),
77            op: ComparisonOp::Equal,
78            rhs: ClassicalValue::Integer(0b01),
79        },
80        PauliX { target: QubitId(2) },
81    )?;
82
83    classical_circuit.add_conditional(
84        ClassicalCondition {
85            lhs: ClassicalValue::Register("alice".to_string()),
86            op: ComparisonOp::Equal,
87            rhs: ClassicalValue::Integer(0b10),
88        },
89        PauliZ { target: QubitId(2) },
90    )?;
91
92    classical_circuit.add_conditional(
93        ClassicalCondition {
94            lhs: ClassicalValue::Register("alice".to_string()),
95            op: ComparisonOp::Equal,
96            rhs: ClassicalValue::Integer(0b11),
97        },
98        PauliX { target: QubitId(2) }, // In reality, this would be X then Z
99    )?;
100
101    println!(
102        "Created teleportation circuit with {} operations",
103        classical_circuit.num_operations()
104    );
105    println!("Bob's qubit 2 receives the state that was on Alice's qubit 0\n");
106
107    Ok(())
108}
Source

pub fn measure( &mut self, qubit: QubitId, register: &str, bit: usize, ) -> QuantRS2Result<()>

Add a measurement

Examples found in repository?
examples/classical_control_demo.rs (line 70)
49fn quantum_teleportation() -> Result<(), Box<dyn std::error::Error>> {
50    println!("Example 2: Quantum Teleportation");
51    println!("--------------------------------");
52
53    // Create Bell pair between qubits 1 and 2
54    let mut circuit = Circuit::<3>::new();
55    circuit.h(1)?;
56    circuit.cnot(1, 2)?;
57
58    // Convert to classical circuit for measurements
59    let mut classical_circuit = circuit.with_classical_control();
60    classical_circuit.add_classical_register("alice", 2)?;
61
62    // Alice's operations
63    classical_circuit.add_gate(quantrs2_core::gate::multi::CNOT {
64        control: QubitId(0),
65        target: QubitId(1),
66    })?;
67    classical_circuit.add_gate(Hadamard { target: QubitId(0) })?;
68
69    // Alice measures her qubits
70    classical_circuit.measure(QubitId(0), "alice", 0)?;
71    classical_circuit.measure(QubitId(1), "alice", 1)?;
72
73    // Bob applies corrections based on Alice's measurements
74    classical_circuit.add_conditional(
75        ClassicalCondition {
76            lhs: ClassicalValue::Register("alice".to_string()),
77            op: ComparisonOp::Equal,
78            rhs: ClassicalValue::Integer(0b01),
79        },
80        PauliX { target: QubitId(2) },
81    )?;
82
83    classical_circuit.add_conditional(
84        ClassicalCondition {
85            lhs: ClassicalValue::Register("alice".to_string()),
86            op: ComparisonOp::Equal,
87            rhs: ClassicalValue::Integer(0b10),
88        },
89        PauliZ { target: QubitId(2) },
90    )?;
91
92    classical_circuit.add_conditional(
93        ClassicalCondition {
94            lhs: ClassicalValue::Register("alice".to_string()),
95            op: ComparisonOp::Equal,
96            rhs: ClassicalValue::Integer(0b11),
97        },
98        PauliX { target: QubitId(2) }, // In reality, this would be X then Z
99    )?;
100
101    println!(
102        "Created teleportation circuit with {} operations",
103        classical_circuit.num_operations()
104    );
105    println!("Bob's qubit 2 receives the state that was on Alice's qubit 0\n");
106
107    Ok(())
108}
Source

pub fn add_conditional<G: GateOp + 'static>( &mut self, condition: ClassicalCondition, gate: G, ) -> QuantRS2Result<()>

Add a conditional gate

Examples found in repository?
examples/classical_control_demo.rs (lines 74-81)
49fn quantum_teleportation() -> Result<(), Box<dyn std::error::Error>> {
50    println!("Example 2: Quantum Teleportation");
51    println!("--------------------------------");
52
53    // Create Bell pair between qubits 1 and 2
54    let mut circuit = Circuit::<3>::new();
55    circuit.h(1)?;
56    circuit.cnot(1, 2)?;
57
58    // Convert to classical circuit for measurements
59    let mut classical_circuit = circuit.with_classical_control();
60    classical_circuit.add_classical_register("alice", 2)?;
61
62    // Alice's operations
63    classical_circuit.add_gate(quantrs2_core::gate::multi::CNOT {
64        control: QubitId(0),
65        target: QubitId(1),
66    })?;
67    classical_circuit.add_gate(Hadamard { target: QubitId(0) })?;
68
69    // Alice measures her qubits
70    classical_circuit.measure(QubitId(0), "alice", 0)?;
71    classical_circuit.measure(QubitId(1), "alice", 1)?;
72
73    // Bob applies corrections based on Alice's measurements
74    classical_circuit.add_conditional(
75        ClassicalCondition {
76            lhs: ClassicalValue::Register("alice".to_string()),
77            op: ComparisonOp::Equal,
78            rhs: ClassicalValue::Integer(0b01),
79        },
80        PauliX { target: QubitId(2) },
81    )?;
82
83    classical_circuit.add_conditional(
84        ClassicalCondition {
85            lhs: ClassicalValue::Register("alice".to_string()),
86            op: ComparisonOp::Equal,
87            rhs: ClassicalValue::Integer(0b10),
88        },
89        PauliZ { target: QubitId(2) },
90    )?;
91
92    classical_circuit.add_conditional(
93        ClassicalCondition {
94            lhs: ClassicalValue::Register("alice".to_string()),
95            op: ComparisonOp::Equal,
96            rhs: ClassicalValue::Integer(0b11),
97        },
98        PauliX { target: QubitId(2) }, // In reality, this would be X then Z
99    )?;
100
101    println!(
102        "Created teleportation circuit with {} operations",
103        classical_circuit.num_operations()
104    );
105    println!("Bob's qubit 2 receives the state that was on Alice's qubit 0\n");
106
107    Ok(())
108}
Source

pub fn reset_classical(&mut self, register: &str) -> QuantRS2Result<()>

Reset a classical register to zero

Source

pub fn num_operations(&self) -> usize

Get the number of operations

Examples found in repository?
examples/classical_control_demo.rs (line 41)
24fn simple_conditional() -> Result<(), Box<dyn std::error::Error>> {
25    println!("Example 1: Simple Conditional Operation");
26    println!("--------------------------------------");
27
28    // Create a circuit with classical control
29    let circuit = ClassicalCircuitBuilder::<2>::new()
30        .classical_register("c", 2)?
31        .gate(Hadamard { target: QubitId(0) })?
32        .measure(QubitId(0), "c", 0)?
33        .conditional(
34            ClassicalCondition::register_equals("c", 1),
35            PauliX { target: QubitId(1) },
36        )?
37        .build();
38
39    println!(
40        "Created circuit with {} operations",
41        circuit.num_operations()
42    );
43    println!("Circuit applies X to qubit 1 if qubit 0 measures to |1⟩\n");
44
45    Ok(())
46}
47
48/// Quantum teleportation with classical communication
49fn quantum_teleportation() -> Result<(), Box<dyn std::error::Error>> {
50    println!("Example 2: Quantum Teleportation");
51    println!("--------------------------------");
52
53    // Create Bell pair between qubits 1 and 2
54    let mut circuit = Circuit::<3>::new();
55    circuit.h(1)?;
56    circuit.cnot(1, 2)?;
57
58    // Convert to classical circuit for measurements
59    let mut classical_circuit = circuit.with_classical_control();
60    classical_circuit.add_classical_register("alice", 2)?;
61
62    // Alice's operations
63    classical_circuit.add_gate(quantrs2_core::gate::multi::CNOT {
64        control: QubitId(0),
65        target: QubitId(1),
66    })?;
67    classical_circuit.add_gate(Hadamard { target: QubitId(0) })?;
68
69    // Alice measures her qubits
70    classical_circuit.measure(QubitId(0), "alice", 0)?;
71    classical_circuit.measure(QubitId(1), "alice", 1)?;
72
73    // Bob applies corrections based on Alice's measurements
74    classical_circuit.add_conditional(
75        ClassicalCondition {
76            lhs: ClassicalValue::Register("alice".to_string()),
77            op: ComparisonOp::Equal,
78            rhs: ClassicalValue::Integer(0b01),
79        },
80        PauliX { target: QubitId(2) },
81    )?;
82
83    classical_circuit.add_conditional(
84        ClassicalCondition {
85            lhs: ClassicalValue::Register("alice".to_string()),
86            op: ComparisonOp::Equal,
87            rhs: ClassicalValue::Integer(0b10),
88        },
89        PauliZ { target: QubitId(2) },
90    )?;
91
92    classical_circuit.add_conditional(
93        ClassicalCondition {
94            lhs: ClassicalValue::Register("alice".to_string()),
95            op: ComparisonOp::Equal,
96            rhs: ClassicalValue::Integer(0b11),
97        },
98        PauliX { target: QubitId(2) }, // In reality, this would be X then Z
99    )?;
100
101    println!(
102        "Created teleportation circuit with {} operations",
103        classical_circuit.num_operations()
104    );
105    println!("Bob's qubit 2 receives the state that was on Alice's qubit 0\n");
106
107    Ok(())
108}
109
110/// Adaptive phase estimation using conditional rotations
111fn adaptive_phase_estimation() -> Result<(), Box<dyn std::error::Error>> {
112    println!("Example 3: Adaptive Phase Estimation");
113    println!("-----------------------------------");
114
115    let circuit = ClassicalCircuitBuilder::<4>::new()
116        .classical_register("phase_bits", 3)?
117        // First estimation round
118        .gate(Hadamard { target: QubitId(0) })?
119        .gate(quantrs2_core::gate::multi::CRZ {
120            control: QubitId(0),
121            target: QubitId(3),
122            theta: std::f64::consts::PI,
123        })?
124        .gate(Hadamard { target: QubitId(0) })?
125        .measure(QubitId(0), "phase_bits", 0)?
126        // Second round (adaptive based on first measurement)
127        .gate(Hadamard { target: QubitId(1) })?
128        .conditional(
129            ClassicalCondition::register_equals("phase_bits", 1),
130            quantrs2_core::gate::single::Phase { target: QubitId(1) }
131        )?
132        .gate(quantrs2_core::gate::multi::CRZ {
133            control: QubitId(1),
134            target: QubitId(3),
135            theta: std::f64::consts::PI / 2.0,
136        })?
137        .gate(Hadamard { target: QubitId(1) })?
138        .measure(QubitId(1), "phase_bits", 1)?
139        // Third round (adaptive based on previous measurements)
140        .gate(Hadamard { target: QubitId(2) })?
141        // Apply phase corrections based on previous measurements
142        .conditional(
143            ClassicalCondition {
144                lhs: ClassicalValue::Register("phase_bits".to_string()),
145                op: ComparisonOp::GreaterEqual,
146                rhs: ClassicalValue::Integer(1),
147            },
148            quantrs2_core::gate::single::RotationZ {
149                target: QubitId(2),
150                theta: -std::f64::consts::PI / 4.0,
151            }
152        )?
153        .gate(quantrs2_core::gate::multi::CRZ {
154            control: QubitId(2),
155            target: QubitId(3),
156            theta: std::f64::consts::PI / 4.0,
157        })?
158        .gate(Hadamard { target: QubitId(2) })?
159        .measure(QubitId(2), "phase_bits", 2)?
160        .build();
161
162    println!(
163        "Created adaptive phase estimation circuit with {} operations",
164        circuit.num_operations()
165    );
166    println!("The circuit adaptively estimates the phase using 3 rounds of measurement\n");
167
168    // Demonstrate builder pattern
169    println!("Alternative: Using standard circuit with conversion");
170    let mut standard_circuit = Circuit::<4>::new();
171    standard_circuit.h(0)?;
172    standard_circuit.h(1)?;
173    standard_circuit.h(2)?;
174
175    let classical = standard_circuit.with_classical_control();
176    println!("Converted standard circuit to classical control\n");
177
178    Ok(())
179}

Auto Trait Implementations§

§

impl<const N: usize> Freeze for ClassicalCircuit<N>

§

impl<const N: usize> !RefUnwindSafe for ClassicalCircuit<N>

§

impl<const N: usize> Send for ClassicalCircuit<N>

§

impl<const N: usize> Sync for ClassicalCircuit<N>

§

impl<const N: usize> Unpin for ClassicalCircuit<N>

§

impl<const N: usize> !UnwindSafe for ClassicalCircuit<N>

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> 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, 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> Ungil for T
where T: Send,