pub struct Circuit<const N: usize> { /* private fields */ }
Expand description
A quantum circuit with a fixed number of qubits
Implementations§
Source§impl<const N: usize> Circuit<N>
impl<const N: usize> Circuit<N>
Sourcepub fn new() -> Self
pub fn new() -> Self
Create a new empty circuit with N qubits
Examples found in repository?
33fn create_sample_circuit() -> Circuit<4> {
34 // Create a circuit that has optimization opportunities
35 let mut circuit = Circuit::<4>::new();
36
37 // Add some gates with optimization opportunities
38 // Pattern 1: Redundant gates (H-H = I, X-X = I)
39 let _ = circuit.h(0);
40 let _ = circuit.h(0);
41
42 // Pattern 2: Commutable gates
43 let _ = circuit.x(1);
44 let _ = circuit.z(0);
45 let _ = circuit.cnot(0, 1);
46
47 // Pattern 3: Mergeable rotations
48 let _ = circuit.rz(2, std::f64::consts::PI / 4.0);
49 let _ = circuit.rz(2, std::f64::consts::PI / 4.0);
50
51 // Pattern 4: Known patterns (H-X-H = Z)
52 let _ = circuit.h(3);
53 let _ = circuit.x(3);
54 let _ = circuit.h(3);
55
56 // Pattern 5: Decomposable gates
57 let _ = circuit.toffoli(0, 1, 2);
58
59 circuit
60}
More examples
35fn demo_structural_equivalence() -> Result<(), Box<dyn std::error::Error>> {
36 println!("1. Structural Equivalence Check");
37 println!(" Checking if two circuits have identical gate sequences");
38
39 // Create two identical Bell state circuits
40 let mut circuit1 = Circuit::<2>::new();
41 circuit1.h(0)?;
42 circuit1.cnot(0, 1)?;
43
44 let mut circuit2 = Circuit::<2>::new();
45 circuit2.h(0)?;
46 circuit2.cnot(0, 1)?;
47
48 // Check structural equivalence
49 let checker = EquivalenceChecker::default();
50 let result = checker.check_structural_equivalence(&circuit1, &circuit2)?;
51
52 println!(" Circuit 1: H(0), CNOT(0,1)");
53 println!(" Circuit 2: H(0), CNOT(0,1)");
54 println!(" Structurally equivalent: {}", result.equivalent);
55 println!(" Details: {}", result.details);
56
57 Ok(())
58}
59
60/// Demonstrate algebraic equivalence (different gates, same result)
61fn demo_algebraic_equivalence() -> Result<(), Box<dyn std::error::Error>> {
62 println!("2. Algebraic Equivalence Check");
63 println!(" Different gate sequences that produce the same result");
64
65 // Circuit 1: X followed by X (should equal identity)
66 let mut circuit1 = Circuit::<1>::new();
67 circuit1.x(0)?;
68 circuit1.x(0)?;
69
70 // Circuit 2: Empty circuit (identity)
71 let circuit2 = Circuit::<1>::new();
72
73 // Check equivalence
74 let mut checker = EquivalenceChecker::default();
75 let result = checker.check_equivalence(&circuit1, &circuit2)?;
76
77 println!(" Circuit 1: X(0), X(0)");
78 println!(" Circuit 2: (empty)");
79 println!(" Equivalent: {}", result.equivalent);
80 println!(" Check type: {:?}", result.check_type);
81
82 // Another example: HZH = X
83 let mut circuit3 = Circuit::<1>::new();
84 circuit3.h(0)?;
85 circuit3.z(0)?;
86 circuit3.h(0)?;
87
88 let mut circuit4 = Circuit::<1>::new();
89 circuit4.x(0)?;
90
91 let result2 = checker.check_structural_equivalence(&circuit3, &circuit4)?;
92
93 println!("\n Circuit 3: H(0), Z(0), H(0)");
94 println!(" Circuit 4: X(0)");
95 println!(" Structurally equivalent: {}", result2.equivalent);
96 println!(" (Note: They are algebraically equivalent but not structurally)");
97
98 Ok(())
99}
100
101/// Demonstrate phase equivalence
102fn demo_phase_equivalence() -> Result<(), Box<dyn std::error::Error>> {
103 println!("3. Global Phase Equivalence");
104 println!(" Circuits that differ only by a global phase");
105
106 // Circuit 1: S gate (phase π/2)
107 let mut circuit1 = Circuit::<1>::new();
108 circuit1.s(0)?;
109
110 // Circuit 2: Z followed by T (phase π + π/4 = 5π/4)
111 // This gives the same result up to global phase
112 let mut circuit2 = Circuit::<1>::new();
113 circuit2.z(0)?;
114 circuit2.t(0)?;
115
116 // Check with phase ignored
117 let mut checker_phase = EquivalenceChecker::new(EquivalenceOptions {
118 tolerance: 1e-10,
119 ignore_global_phase: true,
120 check_all_states: true,
121 max_unitary_qubits: 10,
122 enable_adaptive_tolerance: true,
123 enable_statistical_analysis: true,
124 enable_stability_analysis: true,
125 enable_graph_comparison: false,
126 confidence_level: 0.95,
127 max_condition_number: 1e12,
128 scirs2_config: None,
129 complex_tolerance: 1e-14,
130 enable_parallel_computation: true,
131 });
132
133 // Check without phase ignored
134 let mut checker_no_phase = EquivalenceChecker::new(EquivalenceOptions {
135 tolerance: 1e-10,
136 ignore_global_phase: false,
137 check_all_states: true,
138 max_unitary_qubits: 10,
139 enable_adaptive_tolerance: true,
140 enable_statistical_analysis: true,
141 enable_stability_analysis: true,
142 enable_graph_comparison: false,
143 confidence_level: 0.95,
144 max_condition_number: 1e12,
145 scirs2_config: None,
146 complex_tolerance: 1e-14,
147 enable_parallel_computation: true,
148 });
149
150 println!(" Circuit 1: S(0)");
151 println!(" Circuit 2: Z(0), T(0)");
152
153 // Note: This example is simplified - actual phase relationship may differ
154 println!(" With global phase ignored: (would check if implemented)");
155 println!(" Without global phase: (would check if implemented)");
156
157 Ok(())
158}
159
160/// Demonstrate detection of non-equivalent circuits
161fn demo_non_equivalence() -> Result<(), Box<dyn std::error::Error>> {
162 println!("4. Non-Equivalence Detection");
163 println!(" Detecting when circuits are NOT equivalent");
164
165 // Circuit 1: Bell state |00> + |11>
166 let mut circuit1 = Circuit::<2>::new();
167 circuit1.h(0)?;
168 circuit1.cnot(0, 1)?;
169
170 // Circuit 2: Different entangled state |01> + |10>
171 let mut circuit2 = Circuit::<2>::new();
172 circuit2.h(0)?;
173 circuit2.x(1)?;
174 circuit2.cnot(0, 1)?;
175
176 let checker = EquivalenceChecker::default();
177 let result = checker.check_structural_equivalence(&circuit1, &circuit2)?;
178
179 println!(" Circuit 1: H(0), CNOT(0,1)");
180 println!(" Circuit 2: H(0), X(1), CNOT(0,1)");
181 println!(" Equivalent: {}", result.equivalent);
182 println!(" Details: {}", result.details);
183
184 Ok(())
185}
186
187/// Demonstrate custom tolerance settings
188fn demo_custom_tolerance() -> Result<(), Box<dyn std::error::Error>> {
189 println!("5. Custom Tolerance Settings");
190 println!(" Using different tolerance levels for approximate equivalence");
191
192 // Create circuits that might have small numerical differences
193 let mut circuit1 = Circuit::<1>::new();
194 circuit1.rx(0, PI / 4.0)?;
195
196 let mut circuit2 = Circuit::<1>::new();
197 circuit2.rx(0, PI / 4.0 + 1e-12)?; // Tiny difference
198
199 // Strict tolerance
200 let mut strict_checker = EquivalenceChecker::new(EquivalenceOptions {
201 tolerance: 1e-15,
202 ignore_global_phase: false,
203 check_all_states: true,
204 max_unitary_qubits: 10,
205 enable_adaptive_tolerance: true,
206 enable_statistical_analysis: true,
207 enable_stability_analysis: true,
208 enable_graph_comparison: false,
209 confidence_level: 0.95,
210 max_condition_number: 1e12,
211 scirs2_config: None,
212 complex_tolerance: 1e-14,
213 enable_parallel_computation: true,
214 });
215
216 // Relaxed tolerance
217 let mut relaxed_checker = EquivalenceChecker::new(EquivalenceOptions {
218 tolerance: 1e-10,
219 ignore_global_phase: false,
220 check_all_states: true,
221 max_unitary_qubits: 10,
222 enable_adaptive_tolerance: true,
223 enable_statistical_analysis: true,
224 enable_stability_analysis: true,
225 enable_graph_comparison: false,
226 confidence_level: 0.95,
227 max_condition_number: 1e12,
228 scirs2_config: None,
229 complex_tolerance: 1e-14,
230 enable_parallel_computation: true,
231 });
232
233 println!(" Circuit 1: RX(0, π/4)");
234 println!(" Circuit 2: RX(0, π/4 + 1e-12)");
235 println!(" With strict tolerance (1e-15): (would check if implemented)");
236 println!(" With relaxed tolerance (1e-10): (would check if implemented)");
237
238 Ok(())
239}
240
241/// Additional example: Verify circuit optimization preserves behavior
242fn verify_optimization_example() -> Result<(), Box<dyn std::error::Error>> {
243 println!("\nBonus: Verifying Circuit Optimization");
244
245 // Original circuit with redundant gates
246 let mut original = Circuit::<2>::new();
247 original.h(0)?;
248 original.cnot(0, 1)?;
249 original.cnot(0, 1)?; // This cancels the previous CNOT
250 original.h(0)?;
251
252 // Optimized circuit (manually optimized for this example)
253 let optimized = Circuit::<2>::new();
254 // Empty circuit since H-CNOT-CNOT-H = H-H = I
255
256 let checker = EquivalenceChecker::default();
257 println!(" Original: H(0), CNOT(0,1), CNOT(0,1), H(0)");
258 println!(" Optimized: (empty)");
259
260 // In practice, you would use the circuit optimizer and then verify:
261 // let optimized = original.optimize()?;
262 // let result = checker.check_equivalence(&original, &optimized)?;
263
264 Ok(())
265}
11fn main() -> quantrs2_core::error::QuantRS2Result<()> {
12 println!("=== Noise-Aware Circuit Optimization Demo ===\n");
13
14 // Create a test circuit
15 let mut circuit = Circuit::<4>::new();
16 circuit.add_gate(Hadamard { target: QubitId(0) })?;
17 circuit.add_gate(CNOT {
18 control: QubitId(0),
19 target: QubitId(1),
20 })?;
21 circuit.add_gate(Hadamard { target: QubitId(2) })?;
22 circuit.add_gate(CNOT {
23 control: QubitId(2),
24 target: QubitId(3),
25 })?;
26 circuit.add_gate(CNOT {
27 control: QubitId(1),
28 target: QubitId(2),
29 })?;
30
31 println!("Original circuit:");
32 println!("H(0), CNOT(0,1), H(2), CNOT(2,3), CNOT(1,2)");
33 println!("Total gates: {}\n", circuit.num_gates());
34
35 // Test different noise models
36 demo_uniform_noise(&circuit)?;
37 demo_ibm_noise(&circuit)?;
38 demo_noise_aware_cost_model(&circuit)?;
39 demo_noise_optimization_passes(&circuit)?;
40
41 Ok(())
42}
43
44fn demo_uniform_noise(circuit: &Circuit<4>) -> quantrs2_core::error::QuantRS2Result<()> {
45 println!("--- Uniform Noise Model ---");
46
47 let noise_model = NoiseModel::uniform(4);
48 let optimizer = NoiseAwareOptimizer::new(noise_model.clone());
49
50 println!("Noise characteristics:");
51 println!(
52 " Single-qubit error rate: {:.2e}",
53 noise_model.single_qubit_error(0)
54 );
55 println!(
56 " Two-qubit error rate: {:.2e}",
57 noise_model.two_qubit_error(0, 1)
58 );
59 println!(" T1 time: {:.1} μs", noise_model.t1_time(0));
60 println!(" T2 time: {:.1} μs", noise_model.t2_time(0));
61 println!(" CNOT gate time: {:.1} ns", noise_model.gate_time("CNOT"));
62
63 let original_fidelity = optimizer.estimate_fidelity(circuit);
64 println!("\nOriginal circuit fidelity: {:.4}", original_fidelity);
65
66 let optimized = optimizer.optimize(circuit)?;
67 let optimized_fidelity = optimizer.estimate_fidelity(&optimized);
68 println!("Optimized circuit fidelity: {:.4}", optimized_fidelity);
69
70 if optimized_fidelity > original_fidelity {
71 println!(
72 "✓ Fidelity improved by {:.4}",
73 optimized_fidelity - original_fidelity
74 );
75 } else {
76 println!("→ No fidelity improvement (circuit already optimal)");
77 }
78
79 println!();
80 Ok(())
81}
82
83fn demo_ibm_noise(circuit: &Circuit<4>) -> quantrs2_core::error::QuantRS2Result<()> {
84 println!("--- IBM-like Noise Model ---");
85
86 let noise_model = NoiseModel::ibm_like(4);
87 let coupling_map = CouplingMap::linear(4);
88 let optimizer = NoiseAwareOptimizer::new(noise_model.clone()).with_coupling_map(coupling_map);
89
90 println!("IBM-like noise characteristics:");
91 println!(
92 " Single-qubit error rate: {:.2e}",
93 noise_model.single_qubit_error(0)
94 );
95 println!(
96 " Two-qubit error rate (adjacent): {:.2e}",
97 noise_model.two_qubit_error(0, 1)
98 );
99 println!(" Hadamard gate time: {:.1} ns", noise_model.gate_time("H"));
100 println!(" CNOT gate time: {:.1} ns", noise_model.gate_time("CNOT"));
101
102 let original_fidelity = optimizer.estimate_fidelity(circuit);
103 println!("\nOriginal circuit fidelity: {:.4}", original_fidelity);
104
105 let optimized = optimizer.optimize(circuit)?;
106 let optimized_fidelity = optimizer.estimate_fidelity(&optimized);
107 println!("Optimized circuit fidelity: {:.4}", optimized_fidelity);
108
109 println!("Available optimization passes:");
110 for pass in optimizer.get_passes() {
111 println!(" - {}", pass.name());
112 }
113
114 println!();
115 Ok(())
116}
117
118fn demo_noise_aware_cost_model(circuit: &Circuit<4>) -> quantrs2_core::error::QuantRS2Result<()> {
119 println!("--- Noise-Aware Cost Analysis ---");
120
121 let uniform_noise = NoiseModel::uniform(4);
122 let ibm_noise = NoiseModel::ibm_like(4);
123
124 let uniform_cost_model = NoiseAwareCostModel::new(uniform_noise);
125 let ibm_cost_model = NoiseAwareCostModel::new(ibm_noise);
126
127 let uniform_cost = uniform_cost_model.circuit_cost(circuit);
128 let ibm_cost = ibm_cost_model.circuit_cost(circuit);
129
130 println!("Circuit costs with different noise models:");
131 println!(" Uniform noise model: {:.2}", uniform_cost);
132 println!(" IBM-like noise model: {:.2}", ibm_cost);
133
134 // Analyze individual gate costs
135 println!("\nGate-by-gate cost analysis (IBM model):");
136 for (i, gate) in circuit.gates().iter().enumerate() {
137 let gate_cost = ibm_cost_model.gate_cost(gate.as_ref());
138 println!(" Gate {}: {} - Cost: {:.2}", i, gate.name(), gate_cost);
139 }
140
141 println!();
142 Ok(())
143}
144
145fn demo_noise_optimization_passes(
146 circuit: &Circuit<4>,
147) -> quantrs2_core::error::QuantRS2Result<()> {
148 println!("--- Individual Optimization Passes ---");
149
150 let noise_model = NoiseModel::ibm_like(4);
151 let coupling_map = CouplingMap::linear(4);
152
153 // Test coherence optimization
154 let coherence_opt = CoherenceOptimization::new(noise_model.clone());
155 let cost_model = NoiseAwareCostModel::new(noise_model.clone());
156
157 if coherence_opt.should_apply() {
158 let coherence_result = coherence_opt.apply(circuit, &cost_model)?;
159 println!("✓ Coherence optimization applied");
160 println!(" Original gates: {}", circuit.num_gates());
161 println!(" After coherence opt: {}", coherence_result.num_gates());
162 }
163
164 // Test noise-aware mapping
165 let mapping_opt = NoiseAwareMapping::new(noise_model.clone(), coupling_map.clone());
166 if mapping_opt.should_apply() {
167 let mapping_result = mapping_opt.apply(circuit, &cost_model)?;
168 println!("✓ Noise-aware mapping applied");
169 println!(" Original gates: {}", circuit.num_gates());
170 println!(" After mapping opt: {}", mapping_result.num_gates());
171 }
172
173 // Test dynamical decoupling
174 let dd_opt = DynamicalDecoupling::new(noise_model.clone());
175 if dd_opt.should_apply() {
176 let dd_result = dd_opt.apply(circuit, &cost_model)?;
177 println!("✓ Dynamical decoupling applied");
178 println!(" Original gates: {}", circuit.num_gates());
179 println!(" After DD insertion: {}", dd_result.num_gates());
180 }
181
182 println!();
183 Ok(())
184}
185
186fn demo_fidelity_comparison() -> quantrs2_core::error::QuantRS2Result<()> {
187 println!("--- Fidelity Comparison Across Noise Models ---");
188
189 // Create circuits of different complexity
190 let circuits = vec![
191 create_simple_circuit()?,
192 create_medium_circuit()?,
193 create_complex_circuit()?,
194 ];
195
196 let noise_models = vec![
197 ("Ideal", NoiseModel::new()),
198 ("Uniform", NoiseModel::uniform(4)),
199 ("IBM-like", NoiseModel::ibm_like(4)),
200 ];
201
202 println!(
203 "{:<12} {:<8} {:<8} {:<8}",
204 "Circuit", "Ideal", "Uniform", "IBM-like"
205 );
206 println!("{:-<40}", "");
207
208 for (i, circuit) in circuits.iter().enumerate() {
209 let circuit_name = match i {
210 0 => "Simple",
211 1 => "Medium",
212 2 => "Complex",
213 _ => "Unknown",
214 };
215
216 print!("{:<12}", circuit_name);
217
218 for (_, noise_model) in &noise_models {
219 let optimizer = NoiseAwareOptimizer::new(noise_model.clone());
220 let fidelity = optimizer.estimate_fidelity(circuit);
221 print!(" {:<8.4}", fidelity);
222 }
223 println!();
224 }
225
226 println!();
227 Ok(())
228}
229
230fn create_simple_circuit() -> quantrs2_core::error::QuantRS2Result<Circuit<4>> {
231 let mut circuit = Circuit::<4>::new();
232 circuit.add_gate(Hadamard { target: QubitId(0) })?;
233 circuit.add_gate(CNOT {
234 control: QubitId(0),
235 target: QubitId(1),
236 })?;
237 Ok(circuit)
238}
239
240fn create_medium_circuit() -> quantrs2_core::error::QuantRS2Result<Circuit<4>> {
241 let mut circuit = Circuit::<4>::new();
242 circuit.add_gate(Hadamard { target: QubitId(0) })?;
243 circuit.add_gate(Hadamard { target: QubitId(1) })?;
244 circuit.add_gate(CNOT {
245 control: QubitId(0),
246 target: QubitId(1),
247 })?;
248 circuit.add_gate(CNOT {
249 control: QubitId(1),
250 target: QubitId(2),
251 })?;
252 circuit.add_gate(CNOT {
253 control: QubitId(2),
254 target: QubitId(3),
255 })?;
256 Ok(circuit)
257}
258
259fn create_complex_circuit() -> quantrs2_core::error::QuantRS2Result<Circuit<4>> {
260 let mut circuit = Circuit::<4>::new();
261 for i in 0..4 {
262 circuit.add_gate(Hadamard { target: QubitId(i) })?;
263 }
264 for i in 0..3 {
265 circuit.add_gate(CNOT {
266 control: QubitId(i),
267 target: QubitId(i + 1),
268 })?;
269 }
270 for i in 0..4 {
271 circuit.add_gate(Hadamard { target: QubitId(i) })?;
272 }
273 for i in 0..3 {
274 circuit.add_gate(CNOT {
275 control: QubitId(i + 1),
276 target: QubitId(i),
277 })?;
278 }
279 Ok(circuit)
280}
10fn main() -> quantrs2_core::error::QuantRS2Result<()> {
11 println!("=== Quantum Circuit Routing Demo ===\n");
12
13 // Create a test circuit with gates that require routing
14 let mut circuit = Circuit::<4>::new();
15
16 // Add gates that create connectivity issues on linear devices
17 circuit.add_gate(Hadamard { target: QubitId(0) })?;
18 circuit.add_gate(Hadamard { target: QubitId(1) })?;
19 circuit.add_gate(CNOT {
20 control: QubitId(0),
21 target: QubitId(3),
22 })?; // Non-adjacent!
23 circuit.add_gate(CNOT {
24 control: QubitId(1),
25 target: QubitId(2),
26 })?;
27 circuit.add_gate(CNOT {
28 control: QubitId(2),
29 target: QubitId(0),
30 })?; // Another non-adjacent!
31
32 println!("Original circuit:");
33 println!("H(0), H(1), CNOT(0,3), CNOT(1,2), CNOT(2,0)");
34 println!("Total gates: {}\n", circuit.num_gates());
35
36 // Test different coupling maps
37 demo_linear_coupling(&circuit)?;
38 demo_grid_coupling(&circuit)?;
39 demo_custom_device(&circuit)?;
40
41 Ok(())
42}
63fn demo_circuit_compression() -> quantrs2_core::error::QuantRS2Result<()> {
64 println!("--- Circuit Compression ---");
65
66 // Create a circuit with repetitive structure
67 let mut circuit = Circuit::<4>::new();
68
69 // Add many gates
70 for i in 0..3 {
71 circuit.add_gate(Hadamard { target: QubitId(i) })?;
72 }
73
74 for i in 0..3 {
75 circuit.add_gate(CNOT {
76 control: QubitId(i),
77 target: QubitId(i + 1),
78 })?;
79 }
80
81 for i in 0..4 {
82 circuit.add_gate(T { target: QubitId(i) })?;
83 }
84
85 for i in (1..4).rev() {
86 circuit.add_gate(CNOT {
87 control: QubitId(i - 1),
88 target: QubitId(i),
89 })?;
90 }
91
92 println!("Original circuit: {} gates", circuit.num_gates());
93
94 // Compress using tensor networks
95 let compressor = TensorNetworkCompressor::new(16); // max bond dimension
96 let compressed = compressor.compress(&circuit)?;
97
98 println!(
99 "Compression ratio: {:.2}%",
100 compressed.compression_ratio() * 100.0
101 );
102
103 // Check fidelity
104 let fidelity = compressed.fidelity(&circuit)?;
105 println!("Fidelity with original: {:.6}", fidelity);
106
107 println!();
108 Ok(())
109}
110
111fn demo_mps_representation() -> quantrs2_core::error::QuantRS2Result<()> {
112 println!("--- Matrix Product State Representation ---");
113
114 // Create a circuit that generates an interesting entangled state
115 let mut circuit = Circuit::<6>::new();
116
117 // Create W state: (|100000⟩ + |010000⟩ + |001000⟩ + |000100⟩ + |000010⟩ + |000001⟩)/√6
118 circuit.add_gate(Hadamard { target: QubitId(0) })?;
119 circuit.add_gate(RotationZ {
120 target: QubitId(0),
121 theta: std::f64::consts::PI / 3.0,
122 })?;
123
124 for i in 0..5 {
125 circuit.add_gate(CNOT {
126 control: QubitId(i),
127 target: QubitId(i + 1),
128 })?;
129 }
130
131 println!("Created circuit for W state preparation");
132
133 // Convert to MPS
134 let mps = MatrixProductState::from_circuit(&circuit)?;
135 println!("Converted to MPS representation");
136
137 // Compress with different bond dimensions
138 let bond_dims = vec![2, 4, 8, 16];
139
140 for &max_bond in &bond_dims {
141 let mut mps_copy = MatrixProductState::from_circuit(&circuit)?;
142 mps_copy.compress(max_bond, 1e-10)?;
143
144 // In a real implementation, would calculate actual compression metrics
145 println!("Max bond dimension {}: compression successful", max_bond);
146 }
147
148 println!();
149 Ok(())
150}
151
152fn demo_compression_methods() -> quantrs2_core::error::QuantRS2Result<()> {
153 println!("--- Different Compression Methods ---");
154
155 let mut circuit = Circuit::<5>::new();
156
157 // Build a deep circuit
158 for _ in 0..5 {
159 for i in 0..5 {
160 circuit.add_gate(Hadamard { target: QubitId(i) })?;
161 }
162 for i in 0..4 {
163 circuit.add_gate(CNOT {
164 control: QubitId(i),
165 target: QubitId(i + 1),
166 })?;
167 }
168 }
169
170 println!("Built deep circuit with {} gates", circuit.num_gates());
171
172 // Test different compression methods
173 let methods = vec![
174 CompressionMethod::SVD,
175 CompressionMethod::DMRG,
176 CompressionMethod::TEBD,
177 ];
178
179 for method in methods {
180 let compressor = TensorNetworkCompressor::new(32).with_method(method.clone());
181
182 let compressed = compressor.compress(&circuit)?;
183
184 println!("\n{:?} compression:", method);
185 println!(
186 " Compression ratio: {:.2}%",
187 compressed.compression_ratio() * 100.0
188 );
189
190 // Try to decompress
191 let decompressed = compressed.decompress()?;
192 println!(" Decompressed to {} gates", decompressed.num_gates());
193 }
194
195 println!();
196 Ok(())
197}
198
199fn demo_tensor_contraction() -> quantrs2_core::error::QuantRS2Result<()> {
200 println!("--- Tensor Contraction Optimization ---");
201
202 // Create a circuit with specific structure
203 let mut circuit = Circuit::<4>::new();
204
205 // Layer 1: Single-qubit gates
206 for i in 0..4 {
207 circuit.add_gate(Hadamard { target: QubitId(i) })?;
208 }
209
210 // Layer 2: Entangling gates
211 circuit.add_gate(CNOT {
212 control: QubitId(0),
213 target: QubitId(1),
214 })?;
215 circuit.add_gate(CNOT {
216 control: QubitId(2),
217 target: QubitId(3),
218 })?;
219
220 // Layer 3: Cross entangling
221 circuit.add_gate(CNOT {
222 control: QubitId(1),
223 target: QubitId(2),
224 })?;
225
226 // Convert to tensor network
227 let converter = CircuitToTensorNetwork::<4>::new()
228 .with_max_bond_dim(8)
229 .with_tolerance(1e-12);
230
231 let tn = converter.convert(&circuit)?;
232
233 println!("Converted circuit to tensor network");
234 println!("Network has {} tensors", circuit.num_gates());
235
236 // Contract the network
237 let result = tn.contract_all()?;
238 println!("Contracted to single tensor of rank {}", result.rank());
239
240 println!();
241 Ok(())
242}
243
244fn demo_circuit_analysis() -> quantrs2_core::error::QuantRS2Result<()> {
245 println!("--- Circuit Analysis via Tensor Networks ---");
246
247 // Create circuits to compare
248 let mut circuit1 = Circuit::<3>::new();
249 circuit1.add_gate(Hadamard { target: QubitId(0) })?;
250 circuit1.add_gate(CNOT {
251 control: QubitId(0),
252 target: QubitId(1),
253 })?;
254 circuit1.add_gate(CNOT {
255 control: QubitId(1),
256 target: QubitId(2),
257 })?;
258
259 let mut circuit2 = Circuit::<3>::new();
260 circuit2.add_gate(Hadamard { target: QubitId(0) })?;
261 circuit2.add_gate(CNOT {
262 control: QubitId(0),
263 target: QubitId(2),
264 })?;
265 circuit2.add_gate(CNOT {
266 control: QubitId(0),
267 target: QubitId(1),
268 })?;
269
270 // Convert to MPS for efficient comparison
271 let mps1 = MatrixProductState::from_circuit(&circuit1)?;
272 let mps2 = MatrixProductState::from_circuit(&circuit2)?;
273
274 // Calculate overlap (would indicate circuit similarity)
275 let overlap = mps1.overlap(&mps2)?;
276 println!("Circuit overlap: |⟨ψ₁|ψ₂⟩| = {:.6}", overlap.norm());
277
278 // Compress both circuits
279 let compressor = TensorNetworkCompressor::new(16);
280 let comp1 = compressor.compress(&circuit1)?;
281 let comp2 = compressor.compress(&circuit2)?;
282
283 println!(
284 "Circuit 1 compression: {:.2}%",
285 comp1.compression_ratio() * 100.0
286 );
287 println!(
288 "Circuit 2 compression: {:.2}%",
289 comp2.compression_ratio() * 100.0
290 );
291
292 Ok(())
293}
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}
Sourcepub fn with_capacity(capacity: usize) -> Self
pub fn with_capacity(capacity: usize) -> Self
Create a new circuit with estimated capacity
Sourcepub fn add_gate<G: GateOp + Clone + Send + Sync + 'static>(
&mut self,
gate: G,
) -> QuantRS2Result<&mut Self>
pub fn add_gate<G: GateOp + Clone + Send + Sync + 'static>( &mut self, gate: G, ) -> QuantRS2Result<&mut Self>
Add a gate to the circuit
Examples found in repository?
11fn main() -> quantrs2_core::error::QuantRS2Result<()> {
12 println!("=== Noise-Aware Circuit Optimization Demo ===\n");
13
14 // Create a test circuit
15 let mut circuit = Circuit::<4>::new();
16 circuit.add_gate(Hadamard { target: QubitId(0) })?;
17 circuit.add_gate(CNOT {
18 control: QubitId(0),
19 target: QubitId(1),
20 })?;
21 circuit.add_gate(Hadamard { target: QubitId(2) })?;
22 circuit.add_gate(CNOT {
23 control: QubitId(2),
24 target: QubitId(3),
25 })?;
26 circuit.add_gate(CNOT {
27 control: QubitId(1),
28 target: QubitId(2),
29 })?;
30
31 println!("Original circuit:");
32 println!("H(0), CNOT(0,1), H(2), CNOT(2,3), CNOT(1,2)");
33 println!("Total gates: {}\n", circuit.num_gates());
34
35 // Test different noise models
36 demo_uniform_noise(&circuit)?;
37 demo_ibm_noise(&circuit)?;
38 demo_noise_aware_cost_model(&circuit)?;
39 demo_noise_optimization_passes(&circuit)?;
40
41 Ok(())
42}
43
44fn demo_uniform_noise(circuit: &Circuit<4>) -> quantrs2_core::error::QuantRS2Result<()> {
45 println!("--- Uniform Noise Model ---");
46
47 let noise_model = NoiseModel::uniform(4);
48 let optimizer = NoiseAwareOptimizer::new(noise_model.clone());
49
50 println!("Noise characteristics:");
51 println!(
52 " Single-qubit error rate: {:.2e}",
53 noise_model.single_qubit_error(0)
54 );
55 println!(
56 " Two-qubit error rate: {:.2e}",
57 noise_model.two_qubit_error(0, 1)
58 );
59 println!(" T1 time: {:.1} μs", noise_model.t1_time(0));
60 println!(" T2 time: {:.1} μs", noise_model.t2_time(0));
61 println!(" CNOT gate time: {:.1} ns", noise_model.gate_time("CNOT"));
62
63 let original_fidelity = optimizer.estimate_fidelity(circuit);
64 println!("\nOriginal circuit fidelity: {:.4}", original_fidelity);
65
66 let optimized = optimizer.optimize(circuit)?;
67 let optimized_fidelity = optimizer.estimate_fidelity(&optimized);
68 println!("Optimized circuit fidelity: {:.4}", optimized_fidelity);
69
70 if optimized_fidelity > original_fidelity {
71 println!(
72 "✓ Fidelity improved by {:.4}",
73 optimized_fidelity - original_fidelity
74 );
75 } else {
76 println!("→ No fidelity improvement (circuit already optimal)");
77 }
78
79 println!();
80 Ok(())
81}
82
83fn demo_ibm_noise(circuit: &Circuit<4>) -> quantrs2_core::error::QuantRS2Result<()> {
84 println!("--- IBM-like Noise Model ---");
85
86 let noise_model = NoiseModel::ibm_like(4);
87 let coupling_map = CouplingMap::linear(4);
88 let optimizer = NoiseAwareOptimizer::new(noise_model.clone()).with_coupling_map(coupling_map);
89
90 println!("IBM-like noise characteristics:");
91 println!(
92 " Single-qubit error rate: {:.2e}",
93 noise_model.single_qubit_error(0)
94 );
95 println!(
96 " Two-qubit error rate (adjacent): {:.2e}",
97 noise_model.two_qubit_error(0, 1)
98 );
99 println!(" Hadamard gate time: {:.1} ns", noise_model.gate_time("H"));
100 println!(" CNOT gate time: {:.1} ns", noise_model.gate_time("CNOT"));
101
102 let original_fidelity = optimizer.estimate_fidelity(circuit);
103 println!("\nOriginal circuit fidelity: {:.4}", original_fidelity);
104
105 let optimized = optimizer.optimize(circuit)?;
106 let optimized_fidelity = optimizer.estimate_fidelity(&optimized);
107 println!("Optimized circuit fidelity: {:.4}", optimized_fidelity);
108
109 println!("Available optimization passes:");
110 for pass in optimizer.get_passes() {
111 println!(" - {}", pass.name());
112 }
113
114 println!();
115 Ok(())
116}
117
118fn demo_noise_aware_cost_model(circuit: &Circuit<4>) -> quantrs2_core::error::QuantRS2Result<()> {
119 println!("--- Noise-Aware Cost Analysis ---");
120
121 let uniform_noise = NoiseModel::uniform(4);
122 let ibm_noise = NoiseModel::ibm_like(4);
123
124 let uniform_cost_model = NoiseAwareCostModel::new(uniform_noise);
125 let ibm_cost_model = NoiseAwareCostModel::new(ibm_noise);
126
127 let uniform_cost = uniform_cost_model.circuit_cost(circuit);
128 let ibm_cost = ibm_cost_model.circuit_cost(circuit);
129
130 println!("Circuit costs with different noise models:");
131 println!(" Uniform noise model: {:.2}", uniform_cost);
132 println!(" IBM-like noise model: {:.2}", ibm_cost);
133
134 // Analyze individual gate costs
135 println!("\nGate-by-gate cost analysis (IBM model):");
136 for (i, gate) in circuit.gates().iter().enumerate() {
137 let gate_cost = ibm_cost_model.gate_cost(gate.as_ref());
138 println!(" Gate {}: {} - Cost: {:.2}", i, gate.name(), gate_cost);
139 }
140
141 println!();
142 Ok(())
143}
144
145fn demo_noise_optimization_passes(
146 circuit: &Circuit<4>,
147) -> quantrs2_core::error::QuantRS2Result<()> {
148 println!("--- Individual Optimization Passes ---");
149
150 let noise_model = NoiseModel::ibm_like(4);
151 let coupling_map = CouplingMap::linear(4);
152
153 // Test coherence optimization
154 let coherence_opt = CoherenceOptimization::new(noise_model.clone());
155 let cost_model = NoiseAwareCostModel::new(noise_model.clone());
156
157 if coherence_opt.should_apply() {
158 let coherence_result = coherence_opt.apply(circuit, &cost_model)?;
159 println!("✓ Coherence optimization applied");
160 println!(" Original gates: {}", circuit.num_gates());
161 println!(" After coherence opt: {}", coherence_result.num_gates());
162 }
163
164 // Test noise-aware mapping
165 let mapping_opt = NoiseAwareMapping::new(noise_model.clone(), coupling_map.clone());
166 if mapping_opt.should_apply() {
167 let mapping_result = mapping_opt.apply(circuit, &cost_model)?;
168 println!("✓ Noise-aware mapping applied");
169 println!(" Original gates: {}", circuit.num_gates());
170 println!(" After mapping opt: {}", mapping_result.num_gates());
171 }
172
173 // Test dynamical decoupling
174 let dd_opt = DynamicalDecoupling::new(noise_model.clone());
175 if dd_opt.should_apply() {
176 let dd_result = dd_opt.apply(circuit, &cost_model)?;
177 println!("✓ Dynamical decoupling applied");
178 println!(" Original gates: {}", circuit.num_gates());
179 println!(" After DD insertion: {}", dd_result.num_gates());
180 }
181
182 println!();
183 Ok(())
184}
185
186fn demo_fidelity_comparison() -> quantrs2_core::error::QuantRS2Result<()> {
187 println!("--- Fidelity Comparison Across Noise Models ---");
188
189 // Create circuits of different complexity
190 let circuits = vec![
191 create_simple_circuit()?,
192 create_medium_circuit()?,
193 create_complex_circuit()?,
194 ];
195
196 let noise_models = vec![
197 ("Ideal", NoiseModel::new()),
198 ("Uniform", NoiseModel::uniform(4)),
199 ("IBM-like", NoiseModel::ibm_like(4)),
200 ];
201
202 println!(
203 "{:<12} {:<8} {:<8} {:<8}",
204 "Circuit", "Ideal", "Uniform", "IBM-like"
205 );
206 println!("{:-<40}", "");
207
208 for (i, circuit) in circuits.iter().enumerate() {
209 let circuit_name = match i {
210 0 => "Simple",
211 1 => "Medium",
212 2 => "Complex",
213 _ => "Unknown",
214 };
215
216 print!("{:<12}", circuit_name);
217
218 for (_, noise_model) in &noise_models {
219 let optimizer = NoiseAwareOptimizer::new(noise_model.clone());
220 let fidelity = optimizer.estimate_fidelity(circuit);
221 print!(" {:<8.4}", fidelity);
222 }
223 println!();
224 }
225
226 println!();
227 Ok(())
228}
229
230fn create_simple_circuit() -> quantrs2_core::error::QuantRS2Result<Circuit<4>> {
231 let mut circuit = Circuit::<4>::new();
232 circuit.add_gate(Hadamard { target: QubitId(0) })?;
233 circuit.add_gate(CNOT {
234 control: QubitId(0),
235 target: QubitId(1),
236 })?;
237 Ok(circuit)
238}
239
240fn create_medium_circuit() -> quantrs2_core::error::QuantRS2Result<Circuit<4>> {
241 let mut circuit = Circuit::<4>::new();
242 circuit.add_gate(Hadamard { target: QubitId(0) })?;
243 circuit.add_gate(Hadamard { target: QubitId(1) })?;
244 circuit.add_gate(CNOT {
245 control: QubitId(0),
246 target: QubitId(1),
247 })?;
248 circuit.add_gate(CNOT {
249 control: QubitId(1),
250 target: QubitId(2),
251 })?;
252 circuit.add_gate(CNOT {
253 control: QubitId(2),
254 target: QubitId(3),
255 })?;
256 Ok(circuit)
257}
258
259fn create_complex_circuit() -> quantrs2_core::error::QuantRS2Result<Circuit<4>> {
260 let mut circuit = Circuit::<4>::new();
261 for i in 0..4 {
262 circuit.add_gate(Hadamard { target: QubitId(i) })?;
263 }
264 for i in 0..3 {
265 circuit.add_gate(CNOT {
266 control: QubitId(i),
267 target: QubitId(i + 1),
268 })?;
269 }
270 for i in 0..4 {
271 circuit.add_gate(Hadamard { target: QubitId(i) })?;
272 }
273 for i in 0..3 {
274 circuit.add_gate(CNOT {
275 control: QubitId(i + 1),
276 target: QubitId(i),
277 })?;
278 }
279 Ok(circuit)
280}
More examples
10fn main() -> quantrs2_core::error::QuantRS2Result<()> {
11 println!("=== Quantum Circuit Routing Demo ===\n");
12
13 // Create a test circuit with gates that require routing
14 let mut circuit = Circuit::<4>::new();
15
16 // Add gates that create connectivity issues on linear devices
17 circuit.add_gate(Hadamard { target: QubitId(0) })?;
18 circuit.add_gate(Hadamard { target: QubitId(1) })?;
19 circuit.add_gate(CNOT {
20 control: QubitId(0),
21 target: QubitId(3),
22 })?; // Non-adjacent!
23 circuit.add_gate(CNOT {
24 control: QubitId(1),
25 target: QubitId(2),
26 })?;
27 circuit.add_gate(CNOT {
28 control: QubitId(2),
29 target: QubitId(0),
30 })?; // Another non-adjacent!
31
32 println!("Original circuit:");
33 println!("H(0), H(1), CNOT(0,3), CNOT(1,2), CNOT(2,0)");
34 println!("Total gates: {}\n", circuit.num_gates());
35
36 // Test different coupling maps
37 demo_linear_coupling(&circuit)?;
38 demo_grid_coupling(&circuit)?;
39 demo_custom_device(&circuit)?;
40
41 Ok(())
42}
63fn demo_circuit_compression() -> quantrs2_core::error::QuantRS2Result<()> {
64 println!("--- Circuit Compression ---");
65
66 // Create a circuit with repetitive structure
67 let mut circuit = Circuit::<4>::new();
68
69 // Add many gates
70 for i in 0..3 {
71 circuit.add_gate(Hadamard { target: QubitId(i) })?;
72 }
73
74 for i in 0..3 {
75 circuit.add_gate(CNOT {
76 control: QubitId(i),
77 target: QubitId(i + 1),
78 })?;
79 }
80
81 for i in 0..4 {
82 circuit.add_gate(T { target: QubitId(i) })?;
83 }
84
85 for i in (1..4).rev() {
86 circuit.add_gate(CNOT {
87 control: QubitId(i - 1),
88 target: QubitId(i),
89 })?;
90 }
91
92 println!("Original circuit: {} gates", circuit.num_gates());
93
94 // Compress using tensor networks
95 let compressor = TensorNetworkCompressor::new(16); // max bond dimension
96 let compressed = compressor.compress(&circuit)?;
97
98 println!(
99 "Compression ratio: {:.2}%",
100 compressed.compression_ratio() * 100.0
101 );
102
103 // Check fidelity
104 let fidelity = compressed.fidelity(&circuit)?;
105 println!("Fidelity with original: {:.6}", fidelity);
106
107 println!();
108 Ok(())
109}
110
111fn demo_mps_representation() -> quantrs2_core::error::QuantRS2Result<()> {
112 println!("--- Matrix Product State Representation ---");
113
114 // Create a circuit that generates an interesting entangled state
115 let mut circuit = Circuit::<6>::new();
116
117 // Create W state: (|100000⟩ + |010000⟩ + |001000⟩ + |000100⟩ + |000010⟩ + |000001⟩)/√6
118 circuit.add_gate(Hadamard { target: QubitId(0) })?;
119 circuit.add_gate(RotationZ {
120 target: QubitId(0),
121 theta: std::f64::consts::PI / 3.0,
122 })?;
123
124 for i in 0..5 {
125 circuit.add_gate(CNOT {
126 control: QubitId(i),
127 target: QubitId(i + 1),
128 })?;
129 }
130
131 println!("Created circuit for W state preparation");
132
133 // Convert to MPS
134 let mps = MatrixProductState::from_circuit(&circuit)?;
135 println!("Converted to MPS representation");
136
137 // Compress with different bond dimensions
138 let bond_dims = vec![2, 4, 8, 16];
139
140 for &max_bond in &bond_dims {
141 let mut mps_copy = MatrixProductState::from_circuit(&circuit)?;
142 mps_copy.compress(max_bond, 1e-10)?;
143
144 // In a real implementation, would calculate actual compression metrics
145 println!("Max bond dimension {}: compression successful", max_bond);
146 }
147
148 println!();
149 Ok(())
150}
151
152fn demo_compression_methods() -> quantrs2_core::error::QuantRS2Result<()> {
153 println!("--- Different Compression Methods ---");
154
155 let mut circuit = Circuit::<5>::new();
156
157 // Build a deep circuit
158 for _ in 0..5 {
159 for i in 0..5 {
160 circuit.add_gate(Hadamard { target: QubitId(i) })?;
161 }
162 for i in 0..4 {
163 circuit.add_gate(CNOT {
164 control: QubitId(i),
165 target: QubitId(i + 1),
166 })?;
167 }
168 }
169
170 println!("Built deep circuit with {} gates", circuit.num_gates());
171
172 // Test different compression methods
173 let methods = vec![
174 CompressionMethod::SVD,
175 CompressionMethod::DMRG,
176 CompressionMethod::TEBD,
177 ];
178
179 for method in methods {
180 let compressor = TensorNetworkCompressor::new(32).with_method(method.clone());
181
182 let compressed = compressor.compress(&circuit)?;
183
184 println!("\n{:?} compression:", method);
185 println!(
186 " Compression ratio: {:.2}%",
187 compressed.compression_ratio() * 100.0
188 );
189
190 // Try to decompress
191 let decompressed = compressed.decompress()?;
192 println!(" Decompressed to {} gates", decompressed.num_gates());
193 }
194
195 println!();
196 Ok(())
197}
198
199fn demo_tensor_contraction() -> quantrs2_core::error::QuantRS2Result<()> {
200 println!("--- Tensor Contraction Optimization ---");
201
202 // Create a circuit with specific structure
203 let mut circuit = Circuit::<4>::new();
204
205 // Layer 1: Single-qubit gates
206 for i in 0..4 {
207 circuit.add_gate(Hadamard { target: QubitId(i) })?;
208 }
209
210 // Layer 2: Entangling gates
211 circuit.add_gate(CNOT {
212 control: QubitId(0),
213 target: QubitId(1),
214 })?;
215 circuit.add_gate(CNOT {
216 control: QubitId(2),
217 target: QubitId(3),
218 })?;
219
220 // Layer 3: Cross entangling
221 circuit.add_gate(CNOT {
222 control: QubitId(1),
223 target: QubitId(2),
224 })?;
225
226 // Convert to tensor network
227 let converter = CircuitToTensorNetwork::<4>::new()
228 .with_max_bond_dim(8)
229 .with_tolerance(1e-12);
230
231 let tn = converter.convert(&circuit)?;
232
233 println!("Converted circuit to tensor network");
234 println!("Network has {} tensors", circuit.num_gates());
235
236 // Contract the network
237 let result = tn.contract_all()?;
238 println!("Contracted to single tensor of rank {}", result.rank());
239
240 println!();
241 Ok(())
242}
243
244fn demo_circuit_analysis() -> quantrs2_core::error::QuantRS2Result<()> {
245 println!("--- Circuit Analysis via Tensor Networks ---");
246
247 // Create circuits to compare
248 let mut circuit1 = Circuit::<3>::new();
249 circuit1.add_gate(Hadamard { target: QubitId(0) })?;
250 circuit1.add_gate(CNOT {
251 control: QubitId(0),
252 target: QubitId(1),
253 })?;
254 circuit1.add_gate(CNOT {
255 control: QubitId(1),
256 target: QubitId(2),
257 })?;
258
259 let mut circuit2 = Circuit::<3>::new();
260 circuit2.add_gate(Hadamard { target: QubitId(0) })?;
261 circuit2.add_gate(CNOT {
262 control: QubitId(0),
263 target: QubitId(2),
264 })?;
265 circuit2.add_gate(CNOT {
266 control: QubitId(0),
267 target: QubitId(1),
268 })?;
269
270 // Convert to MPS for efficient comparison
271 let mps1 = MatrixProductState::from_circuit(&circuit1)?;
272 let mps2 = MatrixProductState::from_circuit(&circuit2)?;
273
274 // Calculate overlap (would indicate circuit similarity)
275 let overlap = mps1.overlap(&mps2)?;
276 println!("Circuit overlap: |⟨ψ₁|ψ₂⟩| = {:.6}", overlap.norm());
277
278 // Compress both circuits
279 let compressor = TensorNetworkCompressor::new(16);
280 let comp1 = compressor.compress(&circuit1)?;
281 let comp2 = compressor.compress(&circuit2)?;
282
283 println!(
284 "Circuit 1 compression: {:.2}%",
285 comp1.compression_ratio() * 100.0
286 );
287 println!(
288 "Circuit 2 compression: {:.2}%",
289 comp2.compression_ratio() * 100.0
290 );
291
292 Ok(())
293}
158fn demo_pulse_compilation() -> quantrs2_core::error::QuantRS2Result<()> {
159 println!("--- Circuit to Pulse Compilation ---");
160
161 // Create device configuration
162 let device_config = DeviceConfig::default_config(4);
163 println!("Device configuration:");
164 println!(" Qubits: 4");
165 println!(" Qubit frequencies: ~5 GHz");
166 println!(" Sample rate: {} GS/s", device_config.sample_rate);
167
168 // Create compiler
169 let compiler = PulseCompiler::new(device_config);
170
171 // Create a simple circuit
172 let mut circuit = Circuit::<4>::new();
173 circuit.add_gate(Hadamard { target: QubitId(0) })?;
174 circuit.add_gate(CNOT {
175 control: QubitId(0),
176 target: QubitId(1),
177 })?;
178 circuit.add_gate(RotationZ {
179 target: QubitId(1),
180 theta: PI / 4.0,
181 })?;
182
183 println!("\nCompiling circuit:");
184 for (i, gate) in circuit.gates().iter().enumerate() {
185 println!(" {}: {}", i, gate.name());
186 }
187
188 // Compile to pulses
189 let pulse_schedule = compiler.compile(&circuit)?;
190
191 println!("\nCompiled pulse schedule:");
192 println!(" Duration: {} ns", pulse_schedule.duration);
193 println!(" Instructions: {}", pulse_schedule.instructions.len());
194
195 // Show channel usage
196 let mut channel_usage = std::collections::HashMap::new();
197 for (_, instruction) in &pulse_schedule.instructions {
198 match instruction {
199 PulseInstruction::Play { channel, .. } => {
200 *channel_usage.entry(format!("{:?}", channel)).or_insert(0) += 1;
201 }
202 _ => {}
203 }
204 }
205
206 println!("\nChannel usage:");
207 for (channel, count) in channel_usage {
208 println!(" {}: {} pulses", channel, count);
209 }
210
211 println!();
212 Ok(())
213}
71fn demo_scheduling_strategies() -> quantrs2_core::error::QuantRS2Result<()> {
72 println!("--- Scheduling Strategies ---");
73
74 // Create a test circuit
75 let mut circuit = Circuit::<5>::new();
76
77 // Layer 1: Single-qubit gates
78 for i in 0..5 {
79 circuit.add_gate(Hadamard { target: QubitId(i) })?;
80 }
81
82 // Layer 2: Two-qubit gates
83 circuit.add_gate(CNOT {
84 control: QubitId(0),
85 target: QubitId(1),
86 })?;
87 circuit.add_gate(CNOT {
88 control: QubitId(2),
89 target: QubitId(3),
90 })?;
91 circuit.add_gate(CZ {
92 control: QubitId(1),
93 target: QubitId(2),
94 })?;
95
96 // Layer 3: More single-qubit gates
97 for i in 0..5 {
98 circuit.add_gate(RotationZ {
99 target: QubitId(i),
100 theta: std::f64::consts::PI / 4.0,
101 })?;
102 }
103
104 println!("Test circuit: {} gates on 5 qubits", circuit.num_gates());
105
106 let model = CrosstalkModel::uniform(5, 0.05);
107
108 // Strategy 1: Minimize crosstalk
109 let scheduler1 =
110 CrosstalkScheduler::new(model.clone()).with_strategy(SchedulingStrategy::MinimizeCrosstalk);
111
112 let schedule1 = scheduler1.schedule(&circuit)?;
113
114 println!("\nMinimize Crosstalk Strategy:");
115 println!(" Time slices: {}", schedule1.time_slices.len());
116 println!(" Total crosstalk: {:.4}", schedule1.total_crosstalk);
117 println!(" Execution time: {:.1} ns", schedule1.execution_time);
118
119 // Strategy 2: Minimize time with constraint
120 let scheduler2 =
121 CrosstalkScheduler::new(model.clone()).with_strategy(SchedulingStrategy::MinimizeTime {
122 max_crosstalk: 0.02,
123 });
124
125 let schedule2 = scheduler2.schedule(&circuit)?;
126
127 println!("\nMinimize Time Strategy (max crosstalk = 0.02):");
128 println!(" Time slices: {}", schedule2.time_slices.len());
129 println!(" Total crosstalk: {:.4}", schedule2.total_crosstalk);
130 println!(" Execution time: {:.1} ns", schedule2.execution_time);
131
132 // Strategy 3: Balanced
133 let scheduler3 = CrosstalkScheduler::new(model).with_strategy(SchedulingStrategy::Balanced {
134 time_weight: 0.5,
135 crosstalk_weight: 0.5,
136 });
137
138 let schedule3 = scheduler3.schedule(&circuit)?;
139
140 println!("\nBalanced Strategy:");
141 println!(" Time slices: {}", schedule3.time_slices.len());
142 println!(" Total crosstalk: {:.4}", schedule3.total_crosstalk);
143 println!(" Execution time: {:.1} ns", schedule3.execution_time);
144
145 // Show time slice details for first schedule
146 println!("\nTime slice details (MinimizeCrosstalk):");
147 for (i, slice) in schedule1.time_slices.iter().enumerate() {
148 println!(
149 " Slice {}: {} gates, max crosstalk = {:.4}, duration = {:.1} ns",
150 i,
151 slice.gates.len(),
152 slice.max_crosstalk,
153 slice.duration
154 );
155 }
156
157 println!();
158 Ok(())
159}
160
161fn demo_crosstalk_analysis() -> quantrs2_core::error::QuantRS2Result<()> {
162 println!("--- Cross-talk Analysis ---");
163
164 // Create a circuit with potential crosstalk issues
165 let mut circuit = Circuit::<6>::new();
166
167 // Parallel two-qubit gates on neighboring qubits
168 circuit.add_gate(CNOT {
169 control: QubitId(0),
170 target: QubitId(1),
171 })?;
172 circuit.add_gate(CNOT {
173 control: QubitId(2),
174 target: QubitId(3),
175 })?;
176 circuit.add_gate(CNOT {
177 control: QubitId(4),
178 target: QubitId(5),
179 })?;
180
181 // More gates that might have crosstalk
182 circuit.add_gate(CZ {
183 control: QubitId(1),
184 target: QubitId(2),
185 })?;
186 circuit.add_gate(CZ {
187 control: QubitId(3),
188 target: QubitId(4),
189 })?;
190
191 let model = CrosstalkModel::uniform(6, 0.05);
192 let analyzer = CrosstalkAnalyzer::new(model);
193
194 let analysis = analyzer.analyze(&circuit);
195
196 println!("Circuit analysis:");
197 println!(" Total gates: {}", analysis.total_gates);
198 println!(" Maximum crosstalk: {:.4}", analysis.max_crosstalk);
199 println!(" Problematic pairs: {}", analysis.problematic_pairs.len());
200
201 println!("\nTop problematic gate pairs:");
202 for (i, (g1, g2, crosstalk)) in analysis.problematic_pairs.iter().take(3).enumerate() {
203 println!(
204 " {}. Gates {} and {}: crosstalk = {:.4}",
205 i + 1,
206 g1,
207 g2,
208 crosstalk
209 );
210 }
211
212 // Get reordering suggestions
213 let suggestions = analyzer.suggest_reordering(&circuit)?;
214
215 println!("\nSuggested reorderings:");
216 for suggestion in suggestions.iter().take(3) {
217 println!(
218 " Move gates {} and {} apart: {}",
219 suggestion.gate1, suggestion.gate2, suggestion.reason
220 );
221 println!(
222 " Expected improvement: {:.4}",
223 suggestion.expected_improvement
224 );
225 }
226
227 println!();
228 Ok(())
229}
230
231fn demo_device_specific_scheduling() -> quantrs2_core::error::QuantRS2Result<()> {
232 println!("--- Device-Specific Scheduling ---");
233
234 // Create a realistic device characterization
235 let mut characterization = CrosstalkCharacterization {
236 measured_crosstalk: std::collections::HashMap::new(),
237 single_qubit_measurements: std::collections::HashMap::new(),
238 significance_threshold: 0.01,
239 device_coupling: vec![
240 (0, 1),
241 (1, 2),
242 (2, 3),
243 (3, 4), // Linear connectivity
244 (0, 5),
245 (1, 5),
246 (2, 5),
247 (3, 5),
248 (4, 5), // Star center at qubit 5
249 ],
250 };
251
252 // Add some measured crosstalk values
253 characterization
254 .single_qubit_measurements
255 .insert((0, 1), 0.02);
256 characterization
257 .single_qubit_measurements
258 .insert((1, 2), 0.02);
259 characterization
260 .single_qubit_measurements
261 .insert((0, 5), 0.03);
262 characterization
263 .single_qubit_measurements
264 .insert((1, 5), 0.03);
265
266 characterization
267 .measured_crosstalk
268 .insert(((0, 1), (2, 3)), 0.05);
269 characterization
270 .measured_crosstalk
271 .insert(((0, 1), (3, 4)), 0.02);
272 characterization
273 .measured_crosstalk
274 .insert(((0, 5), (1, 5)), 0.08);
275
276 let model = CrosstalkModel::from_characterization(&characterization);
277 let scheduler = CrosstalkScheduler::new(model);
278
279 // Create circuit that uses the device topology
280 let mut circuit = Circuit::<6>::new();
281
282 // Operations on linear chain
283 circuit.add_gate(Hadamard { target: QubitId(0) })?;
284 circuit.add_gate(CNOT {
285 control: QubitId(0),
286 target: QubitId(1),
287 })?;
288 circuit.add_gate(CNOT {
289 control: QubitId(1),
290 target: QubitId(2),
291 })?;
292
293 // Operations using star center
294 circuit.add_gate(Hadamard { target: QubitId(5) })?;
295 circuit.add_gate(CZ {
296 control: QubitId(5),
297 target: QubitId(0),
298 })?;
299 circuit.add_gate(CZ {
300 control: QubitId(5),
301 target: QubitId(3),
302 })?;
303
304 let schedule = scheduler.schedule(&circuit)?;
305
306 println!("Device-specific schedule:");
307 println!(" Device topology: Linear chain + star center");
308 println!(" Time slices: {}", schedule.time_slices.len());
309 println!(" Total crosstalk: {:.4}", schedule.total_crosstalk);
310
311 println!("\nSchedule details:");
312 for (i, slice) in schedule.time_slices.iter().enumerate() {
313 let gates = &circuit.gates();
314 print!(" Slice {}: ", i);
315 for &gate_idx in &slice.gates {
316 print!("{} ", gates[gate_idx].name());
317 }
318 println!("(crosstalk: {:.4})", slice.max_crosstalk);
319 }
320
321 println!();
322 Ok(())
323}
324
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}
18fn main() -> Result<(), Box<dyn std::error::Error>> {
19 println!("=== QuantRS2 Circuit Advanced Features Demo ===\n");
20
21 // 1. Basic circuit creation
22 println!("1. Creating a basic quantum circuit:");
23 let mut circuit = Circuit::<3>::new();
24 circuit.add_gate(Hadamard { target: QubitId(0) })?;
25 circuit.add_gate(CNOT {
26 control: QubitId(0),
27 target: QubitId(1),
28 })?;
29 circuit.add_gate(CNOT {
30 control: QubitId(1),
31 target: QubitId(2),
32 })?;
33 println!(" Circuit with {} gates created", circuit.gates().len());
34
35 // 2. ZX-calculus optimization
36 println!("\n2. ZX-calculus optimization:");
37 let zx_optimizer = ZXOptimizer::new();
38 let zx_diagram = zx_optimizer.circuit_to_zx(&circuit)?;
39 println!(
40 " ZX diagram with {} nodes created",
41 zx_diagram.nodes.len()
42 );
43
44 // 3. SciRS2 graph analysis
45 println!("\n3. SciRS2 graph analysis:");
46 let mut analyzer = SciRS2CircuitAnalyzer::new();
47 let analysis = analyzer.analyze_circuit(&circuit)?;
48 println!(
49 " Graph metrics: {} nodes, {} edges",
50 analysis.metrics.num_nodes, analysis.metrics.num_edges
51 );
52 println!(" Communities detected: {}", analysis.communities.len());
53
54 // 4. ML-based optimization
55 println!("\n4. ML-based circuit optimization:");
56 let ml_strategy = MLStrategy::NeuralNetwork {
57 architecture: vec![32, 16, 8],
58 learning_rate: 0.001,
59 epochs: 10,
60 batch_size: 16,
61 };
62 let mut ml_optimizer = MLCircuitOptimizer::new(ml_strategy);
63 let ml_result = ml_optimizer.optimize(&circuit)?;
64 println!(
65 " ML optimization completed in {:?}",
66 ml_result.optimization_time
67 );
68
69 // 5. Fault-tolerant compilation
70 println!("\n5. Fault-tolerant compilation:");
71 let code = QECCode::SteaneCode;
72 let ft_compiler = FaultTolerantCompiler::new(code);
73 let ft_circuit = ft_compiler.compile(&circuit)?;
74 println!(
75 " Fault-tolerant circuit: {} physical qubits, {} magic states",
76 ft_circuit.physical_qubit_count, ft_circuit.magic_state_requirements
77 );
78
79 // 6. Photonic circuit conversion
80 println!("\n6. Photonic quantum computation:");
81 let photonic_circuit = PhotonicConverter::quantum_to_photonic(&circuit)?;
82 println!(
83 " Photonic circuit: {} modes, {} gates",
84 photonic_circuit.num_modes,
85 photonic_circuit.gates.len()
86 );
87
88 // 7. Topological quantum computation
89 println!("\n7. Topological quantum computation:");
90 let anyon_model = AnyonModel::fibonacci();
91 let topo_compiler = TopologicalCompiler::new(anyon_model);
92 let topo_circuit = topo_compiler.compile_quantum_circuit(&circuit)?;
93 println!(
94 " Topological circuit: {} anyons, {} braiding operations",
95 topo_circuit.anyon_count(),
96 topo_circuit.total_braiding_operations()
97 );
98
99 // 8. Circuit-to-simulator interface
100 println!("\n8. Circuit compilation for simulators:");
101 let mut compiler = CircuitCompiler::new();
102 compiler.add_target(CompilationTarget {
103 backend: SimulatorBackend::StateVector {
104 max_qubits: 20,
105 use_gpu: false,
106 memory_optimization: MemoryOptimization::Basic,
107 },
108 optimization_level: SimulatorOptimizationLevel::Basic,
109 instruction_set: InstructionSet::Universal,
110 parallel_execution: true,
111 batch_size: Some(10),
112 });
113
114 let compiled = compiler.compile(&circuit)?;
115 println!(
116 " Compiled circuit: {} instructions, estimated memory: {} bytes",
117 compiled.instructions.len(),
118 compiled.resources.memory_bytes
119 );
120
121 // 9. Mid-circuit measurements and feed-forward
122 println!("\n9. Mid-circuit measurements and feed-forward:");
123 let mut measurement_circuit = MeasurementCircuit::<2>::new();
124 measurement_circuit.add_gate(Box::new(Hadamard { target: QubitId(0) }))?;
125 let bit = measurement_circuit.measure(QubitId(0))?;
126
127 let condition = ClassicalCondition::equals(
128 ClassicalValue::Integer(bit as u64),
129 ClassicalValue::Integer(1),
130 );
131 measurement_circuit.add_conditional(condition, Box::new(PauliX { target: QubitId(1) }))?;
132 println!(
133 " Measurement circuit with {} operations created",
134 measurement_circuit.num_operations()
135 );
136
137 // 10. Cross-talk aware scheduling
138 println!("\n10. Cross-talk aware scheduling:");
139 let crosstalk_model = CrosstalkModel::uniform(3, 0.05);
140 let scheduler = CrosstalkScheduler::new(crosstalk_model);
141 let schedule = scheduler.schedule(&circuit)?;
142 println!(
143 " Scheduled into {} time slices, total crosstalk: {:.3}",
144 schedule.time_slices.len(),
145 schedule.total_crosstalk
146 );
147
148 println!("\n=== Demo completed successfully! ===");
149 Ok(())
150}
Sourcepub fn add_gate_arc(
&mut self,
gate: Arc<dyn GateOp + Send + Sync>,
) -> QuantRS2Result<&mut Self>
pub fn add_gate_arc( &mut self, gate: Arc<dyn GateOp + Send + Sync>, ) -> QuantRS2Result<&mut Self>
Add a gate from an Arc (for copying gates between circuits)
Sourcepub fn gates(&self) -> &[Arc<dyn GateOp + Send + Sync>]
pub fn gates(&self) -> &[Arc<dyn GateOp + Send + Sync>]
Get all gates in the circuit
Examples found in repository?
118fn demo_noise_aware_cost_model(circuit: &Circuit<4>) -> quantrs2_core::error::QuantRS2Result<()> {
119 println!("--- Noise-Aware Cost Analysis ---");
120
121 let uniform_noise = NoiseModel::uniform(4);
122 let ibm_noise = NoiseModel::ibm_like(4);
123
124 let uniform_cost_model = NoiseAwareCostModel::new(uniform_noise);
125 let ibm_cost_model = NoiseAwareCostModel::new(ibm_noise);
126
127 let uniform_cost = uniform_cost_model.circuit_cost(circuit);
128 let ibm_cost = ibm_cost_model.circuit_cost(circuit);
129
130 println!("Circuit costs with different noise models:");
131 println!(" Uniform noise model: {:.2}", uniform_cost);
132 println!(" IBM-like noise model: {:.2}", ibm_cost);
133
134 // Analyze individual gate costs
135 println!("\nGate-by-gate cost analysis (IBM model):");
136 for (i, gate) in circuit.gates().iter().enumerate() {
137 let gate_cost = ibm_cost_model.gate_cost(gate.as_ref());
138 println!(" Gate {}: {} - Cost: {:.2}", i, gate.name(), gate_cost);
139 }
140
141 println!();
142 Ok(())
143}
More examples
26fn demo_single_qubit_synthesis() -> quantrs2_core::error::QuantRS2Result<()> {
27 println!("--- Single-Qubit Unitary Synthesis ---");
28
29 let config = SynthesisConfig::default();
30 let synthesizer = SingleQubitSynthesizer::new(config);
31
32 // Test common single-qubit unitaries
33 let unitaries = vec![
34 ("Hadamard", hadamard()),
35 ("Pauli-X", pauli_x()),
36 ("Pauli-Y", pauli_y()),
37 ("Pauli-Z", pauli_z()),
38 ("RX(π/4)", rotation_x(PI / 4.0)),
39 ("RY(π/3)", rotation_y(PI / 3.0)),
40 ("RZ(π/2)", rotation_z(PI / 2.0)),
41 ];
42
43 for (name, unitary) in unitaries {
44 let circuit: Circuit<1> = synthesizer.synthesize(&unitary, QubitId(0))?;
45 println!("{:>12}: {} gates", name, circuit.num_gates());
46
47 // Show gate sequence for Hadamard as example
48 if name == "Hadamard" {
49 println!(" Gate sequence: ");
50 for (i, gate) in circuit.gates().iter().enumerate() {
51 println!(" {}: {}", i, gate.name());
52 }
53 }
54 }
55
56 println!();
57 Ok(())
58}
59
60fn demo_two_qubit_synthesis() -> quantrs2_core::error::QuantRS2Result<()> {
61 println!("--- Two-Qubit Unitary Synthesis ---");
62
63 let config = SynthesisConfig::default();
64 let synthesizer = TwoQubitSynthesizer::new(config);
65
66 // Test CNOT synthesis
67 let cnot_matrix = cnot();
68 let circuit: Circuit<2> = synthesizer.synthesize(&cnot_matrix, QubitId(0), QubitId(1))?;
69
70 println!("CNOT synthesis:");
71 println!(" Gates: {}", circuit.num_gates());
72 println!(" Gate sequence:");
73 for (i, gate) in circuit.gates().iter().enumerate() {
74 println!(" {}: {}", i, gate.name());
75 }
76
77 // Test controlled rotation
78 let theta = PI / 4.0;
79 println!("\nControlled RY(π/4) synthesis:");
80 let controlled_ry_circuit: Circuit<2> = synthesizer.cartan_decomposition(
81 &cnot_matrix, // Placeholder - would be actual controlled-RY matrix
82 QubitId(0),
83 QubitId(1),
84 )?;
85 println!(" Gates: {}", controlled_ry_circuit.num_gates());
86
87 println!();
88 Ok(())
89}
90
91fn demo_common_operations() -> quantrs2_core::error::QuantRS2Result<()> {
92 println!("--- Common Quantum Operations ---");
93
94 let synthesizer = UnitarySynthesizer::default_config();
95
96 // Quantum Fourier Transform
97 println!("Quantum Fourier Transform:");
98 for n_qubits in 2..=4 {
99 let qft_circuit: Circuit<4> = synthesizer.synthesize_qft(n_qubits)?;
100 println!(" QFT-{}: {} gates", n_qubits, qft_circuit.num_gates());
101 }
102
103 // Toffoli gate
104 let toffoli_circuit: Circuit<3> =
105 synthesizer.synthesize_toffoli(QubitId(0), QubitId(1), QubitId(2))?;
106 println!("\nToffoli gate: {} gates", toffoli_circuit.num_gates());
107
108 // Show first few gates of Toffoli decomposition
109 println!(" First 5 gates:");
110 for (i, gate) in toffoli_circuit.gates().iter().take(5).enumerate() {
111 println!(" {}: {}", i, gate.name());
112 }
113
114 println!();
115 Ok(())
116}
158fn demo_pulse_compilation() -> quantrs2_core::error::QuantRS2Result<()> {
159 println!("--- Circuit to Pulse Compilation ---");
160
161 // Create device configuration
162 let device_config = DeviceConfig::default_config(4);
163 println!("Device configuration:");
164 println!(" Qubits: 4");
165 println!(" Qubit frequencies: ~5 GHz");
166 println!(" Sample rate: {} GS/s", device_config.sample_rate);
167
168 // Create compiler
169 let compiler = PulseCompiler::new(device_config);
170
171 // Create a simple circuit
172 let mut circuit = Circuit::<4>::new();
173 circuit.add_gate(Hadamard { target: QubitId(0) })?;
174 circuit.add_gate(CNOT {
175 control: QubitId(0),
176 target: QubitId(1),
177 })?;
178 circuit.add_gate(RotationZ {
179 target: QubitId(1),
180 theta: PI / 4.0,
181 })?;
182
183 println!("\nCompiling circuit:");
184 for (i, gate) in circuit.gates().iter().enumerate() {
185 println!(" {}: {}", i, gate.name());
186 }
187
188 // Compile to pulses
189 let pulse_schedule = compiler.compile(&circuit)?;
190
191 println!("\nCompiled pulse schedule:");
192 println!(" Duration: {} ns", pulse_schedule.duration);
193 println!(" Instructions: {}", pulse_schedule.instructions.len());
194
195 // Show channel usage
196 let mut channel_usage = std::collections::HashMap::new();
197 for (_, instruction) in &pulse_schedule.instructions {
198 match instruction {
199 PulseInstruction::Play { channel, .. } => {
200 *channel_usage.entry(format!("{:?}", channel)).or_insert(0) += 1;
201 }
202 _ => {}
203 }
204 }
205
206 println!("\nChannel usage:");
207 for (channel, count) in channel_usage {
208 println!(" {}: {} pulses", channel, count);
209 }
210
211 println!();
212 Ok(())
213}
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}
231fn demo_device_specific_scheduling() -> quantrs2_core::error::QuantRS2Result<()> {
232 println!("--- Device-Specific Scheduling ---");
233
234 // Create a realistic device characterization
235 let mut characterization = CrosstalkCharacterization {
236 measured_crosstalk: std::collections::HashMap::new(),
237 single_qubit_measurements: std::collections::HashMap::new(),
238 significance_threshold: 0.01,
239 device_coupling: vec![
240 (0, 1),
241 (1, 2),
242 (2, 3),
243 (3, 4), // Linear connectivity
244 (0, 5),
245 (1, 5),
246 (2, 5),
247 (3, 5),
248 (4, 5), // Star center at qubit 5
249 ],
250 };
251
252 // Add some measured crosstalk values
253 characterization
254 .single_qubit_measurements
255 .insert((0, 1), 0.02);
256 characterization
257 .single_qubit_measurements
258 .insert((1, 2), 0.02);
259 characterization
260 .single_qubit_measurements
261 .insert((0, 5), 0.03);
262 characterization
263 .single_qubit_measurements
264 .insert((1, 5), 0.03);
265
266 characterization
267 .measured_crosstalk
268 .insert(((0, 1), (2, 3)), 0.05);
269 characterization
270 .measured_crosstalk
271 .insert(((0, 1), (3, 4)), 0.02);
272 characterization
273 .measured_crosstalk
274 .insert(((0, 5), (1, 5)), 0.08);
275
276 let model = CrosstalkModel::from_characterization(&characterization);
277 let scheduler = CrosstalkScheduler::new(model);
278
279 // Create circuit that uses the device topology
280 let mut circuit = Circuit::<6>::new();
281
282 // Operations on linear chain
283 circuit.add_gate(Hadamard { target: QubitId(0) })?;
284 circuit.add_gate(CNOT {
285 control: QubitId(0),
286 target: QubitId(1),
287 })?;
288 circuit.add_gate(CNOT {
289 control: QubitId(1),
290 target: QubitId(2),
291 })?;
292
293 // Operations using star center
294 circuit.add_gate(Hadamard { target: QubitId(5) })?;
295 circuit.add_gate(CZ {
296 control: QubitId(5),
297 target: QubitId(0),
298 })?;
299 circuit.add_gate(CZ {
300 control: QubitId(5),
301 target: QubitId(3),
302 })?;
303
304 let schedule = scheduler.schedule(&circuit)?;
305
306 println!("Device-specific schedule:");
307 println!(" Device topology: Linear chain + star center");
308 println!(" Time slices: {}", schedule.time_slices.len());
309 println!(" Total crosstalk: {:.4}", schedule.total_crosstalk);
310
311 println!("\nSchedule details:");
312 for (i, slice) in schedule.time_slices.iter().enumerate() {
313 let gates = &circuit.gates();
314 print!(" Slice {}: ", i);
315 for &gate_idx in &slice.gates {
316 print!("{} ", gates[gate_idx].name());
317 }
318 println!("(crosstalk: {:.4})", slice.max_crosstalk);
319 }
320
321 println!();
322 Ok(())
323}
324
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}
18fn main() -> Result<(), Box<dyn std::error::Error>> {
19 println!("=== QuantRS2 Circuit Advanced Features Demo ===\n");
20
21 // 1. Basic circuit creation
22 println!("1. Creating a basic quantum circuit:");
23 let mut circuit = Circuit::<3>::new();
24 circuit.add_gate(Hadamard { target: QubitId(0) })?;
25 circuit.add_gate(CNOT {
26 control: QubitId(0),
27 target: QubitId(1),
28 })?;
29 circuit.add_gate(CNOT {
30 control: QubitId(1),
31 target: QubitId(2),
32 })?;
33 println!(" Circuit with {} gates created", circuit.gates().len());
34
35 // 2. ZX-calculus optimization
36 println!("\n2. ZX-calculus optimization:");
37 let zx_optimizer = ZXOptimizer::new();
38 let zx_diagram = zx_optimizer.circuit_to_zx(&circuit)?;
39 println!(
40 " ZX diagram with {} nodes created",
41 zx_diagram.nodes.len()
42 );
43
44 // 3. SciRS2 graph analysis
45 println!("\n3. SciRS2 graph analysis:");
46 let mut analyzer = SciRS2CircuitAnalyzer::new();
47 let analysis = analyzer.analyze_circuit(&circuit)?;
48 println!(
49 " Graph metrics: {} nodes, {} edges",
50 analysis.metrics.num_nodes, analysis.metrics.num_edges
51 );
52 println!(" Communities detected: {}", analysis.communities.len());
53
54 // 4. ML-based optimization
55 println!("\n4. ML-based circuit optimization:");
56 let ml_strategy = MLStrategy::NeuralNetwork {
57 architecture: vec![32, 16, 8],
58 learning_rate: 0.001,
59 epochs: 10,
60 batch_size: 16,
61 };
62 let mut ml_optimizer = MLCircuitOptimizer::new(ml_strategy);
63 let ml_result = ml_optimizer.optimize(&circuit)?;
64 println!(
65 " ML optimization completed in {:?}",
66 ml_result.optimization_time
67 );
68
69 // 5. Fault-tolerant compilation
70 println!("\n5. Fault-tolerant compilation:");
71 let code = QECCode::SteaneCode;
72 let ft_compiler = FaultTolerantCompiler::new(code);
73 let ft_circuit = ft_compiler.compile(&circuit)?;
74 println!(
75 " Fault-tolerant circuit: {} physical qubits, {} magic states",
76 ft_circuit.physical_qubit_count, ft_circuit.magic_state_requirements
77 );
78
79 // 6. Photonic circuit conversion
80 println!("\n6. Photonic quantum computation:");
81 let photonic_circuit = PhotonicConverter::quantum_to_photonic(&circuit)?;
82 println!(
83 " Photonic circuit: {} modes, {} gates",
84 photonic_circuit.num_modes,
85 photonic_circuit.gates.len()
86 );
87
88 // 7. Topological quantum computation
89 println!("\n7. Topological quantum computation:");
90 let anyon_model = AnyonModel::fibonacci();
91 let topo_compiler = TopologicalCompiler::new(anyon_model);
92 let topo_circuit = topo_compiler.compile_quantum_circuit(&circuit)?;
93 println!(
94 " Topological circuit: {} anyons, {} braiding operations",
95 topo_circuit.anyon_count(),
96 topo_circuit.total_braiding_operations()
97 );
98
99 // 8. Circuit-to-simulator interface
100 println!("\n8. Circuit compilation for simulators:");
101 let mut compiler = CircuitCompiler::new();
102 compiler.add_target(CompilationTarget {
103 backend: SimulatorBackend::StateVector {
104 max_qubits: 20,
105 use_gpu: false,
106 memory_optimization: MemoryOptimization::Basic,
107 },
108 optimization_level: SimulatorOptimizationLevel::Basic,
109 instruction_set: InstructionSet::Universal,
110 parallel_execution: true,
111 batch_size: Some(10),
112 });
113
114 let compiled = compiler.compile(&circuit)?;
115 println!(
116 " Compiled circuit: {} instructions, estimated memory: {} bytes",
117 compiled.instructions.len(),
118 compiled.resources.memory_bytes
119 );
120
121 // 9. Mid-circuit measurements and feed-forward
122 println!("\n9. Mid-circuit measurements and feed-forward:");
123 let mut measurement_circuit = MeasurementCircuit::<2>::new();
124 measurement_circuit.add_gate(Box::new(Hadamard { target: QubitId(0) }))?;
125 let bit = measurement_circuit.measure(QubitId(0))?;
126
127 let condition = ClassicalCondition::equals(
128 ClassicalValue::Integer(bit as u64),
129 ClassicalValue::Integer(1),
130 );
131 measurement_circuit.add_conditional(condition, Box::new(PauliX { target: QubitId(1) }))?;
132 println!(
133 " Measurement circuit with {} operations created",
134 measurement_circuit.num_operations()
135 );
136
137 // 10. Cross-talk aware scheduling
138 println!("\n10. Cross-talk aware scheduling:");
139 let crosstalk_model = CrosstalkModel::uniform(3, 0.05);
140 let scheduler = CrosstalkScheduler::new(crosstalk_model);
141 let schedule = scheduler.schedule(&circuit)?;
142 println!(
143 " Scheduled into {} time slices, total crosstalk: {:.3}",
144 schedule.time_slices.len(),
145 schedule.total_crosstalk
146 );
147
148 println!("\n=== Demo completed successfully! ===");
149 Ok(())
150}
Sourcepub fn gates_as_boxes(&self) -> Vec<Box<dyn GateOp>>
pub fn gates_as_boxes(&self) -> Vec<Box<dyn GateOp>>
Get gates as Vec for compatibility with existing optimization code
Sourcepub fn count_gates_by_type(&self) -> HashMap<String, usize>
pub fn count_gates_by_type(&self) -> HashMap<String, usize>
Circuit introspection methods for optimization Count gates by type
Sourcepub fn calculate_depth(&self) -> usize
pub fn calculate_depth(&self) -> usize
Calculate circuit depth (longest sequential path)
Sourcepub fn count_two_qubit_gates(&self) -> usize
pub fn count_two_qubit_gates(&self) -> usize
Count two-qubit gates
Sourcepub fn count_multi_qubit_gates(&self) -> usize
pub fn count_multi_qubit_gates(&self) -> usize
Count multi-qubit gates (3 or more qubits)
Sourcepub fn calculate_critical_path(&self) -> usize
pub fn calculate_critical_path(&self) -> usize
Calculate the critical path length (same as depth for now, but could be enhanced)
Sourcepub fn calculate_gate_density(&self) -> f64
pub fn calculate_gate_density(&self) -> f64
Calculate gate density (gates per qubit)
Sourcepub fn get_used_qubits(&self) -> HashSet<QubitId>
pub fn get_used_qubits(&self) -> HashSet<QubitId>
Get all unique qubits used in the circuit
Sourcepub fn uses_all_qubits(&self) -> bool
pub fn uses_all_qubits(&self) -> bool
Check if the circuit uses all available qubits
Sourcepub fn gates_on_qubit(
&self,
target_qubit: QubitId,
) -> Vec<&Arc<dyn GateOp + Send + Sync>>
pub fn gates_on_qubit( &self, target_qubit: QubitId, ) -> Vec<&Arc<dyn GateOp + Send + Sync>>
Get gates that operate on a specific qubit
Sourcepub fn gates_in_range(
&self,
start: usize,
end: usize,
) -> &[Arc<dyn GateOp + Send + Sync>]
pub fn gates_in_range( &self, start: usize, end: usize, ) -> &[Arc<dyn GateOp + Send + Sync>]
Get gates between two indices (inclusive)
Sourcepub fn get_stats(&self) -> CircuitStats
pub fn get_stats(&self) -> CircuitStats
Get circuit statistics summary
Sourcepub fn num_qubits(&self) -> usize
pub fn num_qubits(&self) -> usize
Get the number of qubits in the circuit
Examples found in repository?
12fn main() -> Result<(), Box<dyn std::error::Error>> {
13 println!("🌐 Distributed Circuit Execution Demo");
14 println!("====================================\n");
15
16 // Example 1: Setting up a distributed executor
17 println!("1. Creating Distributed Executor");
18 println!("--------------------------------");
19
20 let mut executor = DistributedExecutor::new();
21 println!("Created distributed executor with default configuration");
22 println!(" Load balancing: {:?}", executor.load_balancer.strategy);
23 println!(" Scheduling policy: {:?}", executor.scheduler.policy);
24 println!(
25 " Fault tolerance enabled: {}",
26 executor.fault_tolerance.enable_failover
27 );
28 println!(
29 " Redundancy level: {}",
30 executor.fault_tolerance.redundancy_level
31 );
32
33 // Example 2: Adding different types of backends
34 println!("\n2. Adding Execution Backends");
35 println!("----------------------------");
36
37 // Add a quantum hardware backend
38 let hardware_backend = create_hardware_backend();
39 println!("Adding hardware backend: {}", hardware_backend.id);
40 executor.add_backend(hardware_backend)?;
41
42 // Add a simulator backend
43 let simulator_backend = create_simulator_backend();
44 println!("Adding simulator backend: {}", simulator_backend.id);
45 executor.add_backend(simulator_backend)?;
46
47 // Add a cloud service backend
48 let cloud_backend = create_cloud_backend();
49 println!("Adding cloud backend: {}", cloud_backend.id);
50 executor.add_backend(cloud_backend)?;
51
52 // Add a hybrid backend
53 let hybrid_backend = create_hybrid_backend();
54 println!("Adding hybrid backend: {}", hybrid_backend.id);
55 executor.add_backend(hybrid_backend)?;
56
57 println!("Total backends added: {}", executor.backends.len());
58
59 // Example 3: System health status
60 println!("\n3. System Health Status");
61 println!("-----------------------");
62
63 let health = executor.get_health_status();
64 println!("System health:");
65 println!(" Total backends: {}", health.total_backends);
66 println!(" Available backends: {}", health.available_backends);
67 println!(" Total qubits: {}", health.total_qubits);
68 println!(
69 " Average queue time: {:.2} seconds",
70 health.average_queue_time
71 );
72 println!(" System load: {:.1}%", health.system_load * 100.0);
73
74 // Example 4: Creating and submitting jobs
75 println!("\n4. Creating and Submitting Jobs");
76 println!("-------------------------------");
77
78 // Create different types of circuits for testing
79 let jobs = create_test_jobs();
80
81 for (i, job) in jobs.iter().enumerate() {
82 println!(
83 "Job {}: {} ({} qubits, {} gates, priority: {:?})",
84 i + 1,
85 job.id,
86 job.circuit.num_qubits(),
87 job.circuit.num_gates(),
88 job.priority
89 );
90
91 match executor.submit_job(job.clone()) {
92 Ok(job_id) => println!(" ✅ Submitted successfully: {}", job_id),
93 Err(e) => println!(" ❌ Submission failed: {}", e),
94 }
95 }
96
97 // Example 5: Different load balancing strategies
98 println!("\n5. Load Balancing Strategies");
99 println!("----------------------------");
100
101 let strategies = vec![
102 ("Round Robin", LoadBalancingStrategy::RoundRobin),
103 ("Least Connections", LoadBalancingStrategy::LeastConnections),
104 ("Least Queue Time", LoadBalancingStrategy::LeastQueueTime),
105 ("Best Performance", LoadBalancingStrategy::BestPerformance),
106 ];
107
108 for (name, strategy) in strategies {
109 executor.load_balancer.strategy = strategy.clone();
110 println!(" {}: {:?}", name, strategy);
111 }
112
113 // Example 6: Backend types and capabilities
114 println!("\n6. Backend Types and Capabilities");
115 println!("---------------------------------");
116
117 for backend in &executor.backends {
118 println!("Backend: {} ({:?})", backend.id, backend.status);
119 match &backend.backend_type {
120 BackendType::Hardware {
121 vendor,
122 model,
123 location,
124 } => {
125 println!(" Type: Hardware ({} {} in {})", vendor, model, location);
126 }
127 BackendType::Simulator {
128 simulator_type,
129 host,
130 } => {
131 println!(" Type: Simulator ({:?} on {})", simulator_type, host);
132 }
133 BackendType::CloudService {
134 provider,
135 service_name,
136 region,
137 } => {
138 println!(
139 " Type: Cloud ({} {} in {})",
140 provider, service_name, region
141 );
142 }
143 BackendType::Hybrid {
144 quantum_backend: _,
145 classical_resources,
146 } => {
147 println!(
148 " Type: Hybrid ({} CPU cores, {:.1} GB memory)",
149 classical_resources.cpu_cores, classical_resources.memory_gb
150 );
151 }
152 }
153
154 println!(" Capabilities:");
155 println!(" Max qubits: {}", backend.performance.max_qubits);
156 println!(" Max depth: {}", backend.performance.max_depth);
157 println!(
158 " Supported gates: {:?}",
159 backend.capabilities.supported_gates
160 );
161 println!(
162 " Mid-circuit measurements: {}",
163 backend.capabilities.mid_circuit_measurements
164 );
165 println!(
166 " Queue length: {}/{}",
167 backend.queue_info.queue_length, backend.queue_info.max_queue_size
168 );
169 println!(
170 " Estimated wait time: {:.1} seconds",
171 backend.queue_info.estimated_wait_time
172 );
173 println!();
174 }
175
176 // Example 7: Execution parameters and error mitigation
177 println!("7. Execution Parameters and Error Mitigation");
178 println!("--------------------------------------------");
179
180 let error_mitigation_techniques = vec![
181 (
182 "Readout Error Mitigation",
183 ErrorMitigation::ReadoutErrorMitigation,
184 ),
185 (
186 "Zero Noise Extrapolation",
187 ErrorMitigation::ZeroNoiseExtrapolation,
188 ),
189 (
190 "Clifford Data Regression",
191 ErrorMitigation::CliffordDataRegression,
192 ),
193 (
194 "Symmetry Verification",
195 ErrorMitigation::SymmetryVerification,
196 ),
197 ];
198
199 for (name, technique) in error_mitigation_techniques {
200 println!(" {}: {:?}", name, technique);
201 }
202
203 let result_formats = vec![
204 ("Counts", ResultFormat::Counts),
205 ("Probabilities", ResultFormat::Probabilities),
206 ("Statevector", ResultFormat::Statevector),
207 ("Expectation Values", ResultFormat::ExpectationValues),
208 ];
209
210 println!("\nResult formats:");
211 for (name, format) in result_formats {
212 println!(" {}: {:?}", name, format);
213 }
214
215 // Example 8: Fault tolerance and redundancy
216 println!("\n8. Fault Tolerance and Redundancy");
217 println!("---------------------------------");
218
219 println!("Current fault tolerance configuration:");
220 println!(
221 " Failover enabled: {}",
222 executor.fault_tolerance.enable_failover
223 );
224 println!(
225 " Redundancy level: {}",
226 executor.fault_tolerance.redundancy_level
227 );
228 println!(
229 " Error correction: {:?}",
230 executor.fault_tolerance.error_correction
231 );
232
233 // Demonstrate different error correction strategies
234 let error_correction_strategies = vec![
235 ("None", ErrorCorrectionStrategy::None),
236 ("Majority Voting", ErrorCorrectionStrategy::MajorityVoting),
237 (
238 "Quantum Error Correction",
239 ErrorCorrectionStrategy::QuantumErrorCorrection,
240 ),
241 (
242 "Classical Post-processing",
243 ErrorCorrectionStrategy::ClassicalPostProcessing,
244 ),
245 ];
246
247 println!("\nAvailable error correction strategies:");
248 for (name, strategy) in error_correction_strategies {
249 println!(" {}: {:?}", name, strategy);
250 }
251
252 // Example 9: Resource management and allocation
253 println!("\n9. Resource Management and Allocation");
254 println!("------------------------------------");
255
256 println!("Resource pool:");
257 println!(
258 " Total qubits: {}",
259 executor.resource_manager.resource_pool.total_qubits
260 );
261 println!(
262 " Available slots: {}",
263 executor.resource_manager.resource_pool.available_slots
264 );
265 println!(
266 " Memory pool: {:.1} GB",
267 executor.resource_manager.resource_pool.memory_pool
268 );
269 println!(
270 " Compute pool: {:.1} CPU hours",
271 executor.resource_manager.resource_pool.compute_pool
272 );
273
274 println!("\nAllocation policies:");
275 if let Some(max_qubits) = executor
276 .resource_manager
277 .allocation_policies
278 .max_qubits_per_user
279 {
280 println!(" Max qubits per user: {}", max_qubits);
281 }
282 if let Some(max_time) = executor
283 .resource_manager
284 .allocation_policies
285 .max_execution_time
286 {
287 println!(" Max execution time: {:.1} seconds", max_time);
288 }
289 println!(
290 " Fair share: {}",
291 executor.resource_manager.allocation_policies.fair_share
292 );
293 println!(
294 " Reserved resources: {:.1}%",
295 executor
296 .resource_manager
297 .allocation_policies
298 .reserved_resources
299 * 100.0
300 );
301
302 // Example 10: Network configuration and authentication
303 println!("\n10. Network Configuration and Authentication");
304 println!("-------------------------------------------");
305
306 for backend in &executor.backends {
307 println!(
308 "Backend {}: {}",
309 backend.id, backend.network_config.endpoint
310 );
311 println!(
312 " Auth type: {:?}",
313 backend.network_config.credentials.auth_type
314 );
315 println!(
316 " Connection timeout: {:.1}s",
317 backend.network_config.timeouts.connection_timeout
318 );
319 println!(
320 " Request timeout: {:.1}s",
321 backend.network_config.timeouts.request_timeout
322 );
323 println!(
324 " Max retries: {}",
325 backend.network_config.retry_policy.max_retries
326 );
327 println!(
328 " Backoff strategy: {:?}",
329 backend.network_config.retry_policy.backoff_strategy
330 );
331 }
332
333 // Example 11: Job status and results (mock)
334 println!("\n11. Job Status and Results");
335 println!("--------------------------");
336
337 for job in jobs.iter().take(3) {
338 let status = executor.get_job_status(&job.id)?;
339 println!("Job {}: {:?}", job.id, status);
340
341 // Mock getting results for completed jobs
342 if status == ExecutionStatus::Queued {
343 let result = executor.get_results(&job.id)?;
344 println!(" Status: {:?}", result.status);
345 println!(" Backends used: {:?}", result.metadata.backends_used);
346 println!(" Total time: {:?}", result.metadata.total_time);
347 println!(" Queue time: {:?}", result.metadata.queue_time);
348 println!(" Resource usage:");
349 println!(
350 " CPU hours: {:.3}",
351 result.metadata.resource_usage.cpu_hours
352 );
353 println!(
354 " Memory hours: {:.3}",
355 result.metadata.resource_usage.memory_hours
356 );
357 println!(
358 " Qubit hours: {:.3}",
359 result.metadata.resource_usage.qubit_hours
360 );
361 println!(
362 " Network usage: {:.3} GB",
363 result.metadata.resource_usage.network_usage
364 );
365 }
366 }
367
368 // Example 12: Connectivity topologies
369 println!("\n12. Connectivity Topologies");
370 println!("---------------------------");
371
372 let topologies = vec![
373 ("Linear", distributed::TopologyType::Linear),
374 (
375 "2D Grid (3x3)",
376 distributed::TopologyType::Grid2D { rows: 3, cols: 3 },
377 ),
378 ("All-to-all", distributed::TopologyType::AllToAll),
379 (
380 "Random (70% density)",
381 distributed::TopologyType::Random { density: 0.7 },
382 ),
383 ];
384
385 for (name, topology) in topologies {
386 println!(" {}: {:?}", name, topology);
387 }
388
389 println!("\n✅ Distributed Circuit Execution Demo completed!");
390 println!("\nNote: This demo shows the distributed execution framework structure.");
391 println!("Real distributed execution requires actual quantum backends and networking.");
392
393 Ok(())
394}
Sourcepub fn num_gates(&self) -> usize
pub fn num_gates(&self) -> usize
Get the number of gates in the circuit
Examples found in repository?
11fn main() -> quantrs2_core::error::QuantRS2Result<()> {
12 println!("=== Noise-Aware Circuit Optimization Demo ===\n");
13
14 // Create a test circuit
15 let mut circuit = Circuit::<4>::new();
16 circuit.add_gate(Hadamard { target: QubitId(0) })?;
17 circuit.add_gate(CNOT {
18 control: QubitId(0),
19 target: QubitId(1),
20 })?;
21 circuit.add_gate(Hadamard { target: QubitId(2) })?;
22 circuit.add_gate(CNOT {
23 control: QubitId(2),
24 target: QubitId(3),
25 })?;
26 circuit.add_gate(CNOT {
27 control: QubitId(1),
28 target: QubitId(2),
29 })?;
30
31 println!("Original circuit:");
32 println!("H(0), CNOT(0,1), H(2), CNOT(2,3), CNOT(1,2)");
33 println!("Total gates: {}\n", circuit.num_gates());
34
35 // Test different noise models
36 demo_uniform_noise(&circuit)?;
37 demo_ibm_noise(&circuit)?;
38 demo_noise_aware_cost_model(&circuit)?;
39 demo_noise_optimization_passes(&circuit)?;
40
41 Ok(())
42}
43
44fn demo_uniform_noise(circuit: &Circuit<4>) -> quantrs2_core::error::QuantRS2Result<()> {
45 println!("--- Uniform Noise Model ---");
46
47 let noise_model = NoiseModel::uniform(4);
48 let optimizer = NoiseAwareOptimizer::new(noise_model.clone());
49
50 println!("Noise characteristics:");
51 println!(
52 " Single-qubit error rate: {:.2e}",
53 noise_model.single_qubit_error(0)
54 );
55 println!(
56 " Two-qubit error rate: {:.2e}",
57 noise_model.two_qubit_error(0, 1)
58 );
59 println!(" T1 time: {:.1} μs", noise_model.t1_time(0));
60 println!(" T2 time: {:.1} μs", noise_model.t2_time(0));
61 println!(" CNOT gate time: {:.1} ns", noise_model.gate_time("CNOT"));
62
63 let original_fidelity = optimizer.estimate_fidelity(circuit);
64 println!("\nOriginal circuit fidelity: {:.4}", original_fidelity);
65
66 let optimized = optimizer.optimize(circuit)?;
67 let optimized_fidelity = optimizer.estimate_fidelity(&optimized);
68 println!("Optimized circuit fidelity: {:.4}", optimized_fidelity);
69
70 if optimized_fidelity > original_fidelity {
71 println!(
72 "✓ Fidelity improved by {:.4}",
73 optimized_fidelity - original_fidelity
74 );
75 } else {
76 println!("→ No fidelity improvement (circuit already optimal)");
77 }
78
79 println!();
80 Ok(())
81}
82
83fn demo_ibm_noise(circuit: &Circuit<4>) -> quantrs2_core::error::QuantRS2Result<()> {
84 println!("--- IBM-like Noise Model ---");
85
86 let noise_model = NoiseModel::ibm_like(4);
87 let coupling_map = CouplingMap::linear(4);
88 let optimizer = NoiseAwareOptimizer::new(noise_model.clone()).with_coupling_map(coupling_map);
89
90 println!("IBM-like noise characteristics:");
91 println!(
92 " Single-qubit error rate: {:.2e}",
93 noise_model.single_qubit_error(0)
94 );
95 println!(
96 " Two-qubit error rate (adjacent): {:.2e}",
97 noise_model.two_qubit_error(0, 1)
98 );
99 println!(" Hadamard gate time: {:.1} ns", noise_model.gate_time("H"));
100 println!(" CNOT gate time: {:.1} ns", noise_model.gate_time("CNOT"));
101
102 let original_fidelity = optimizer.estimate_fidelity(circuit);
103 println!("\nOriginal circuit fidelity: {:.4}", original_fidelity);
104
105 let optimized = optimizer.optimize(circuit)?;
106 let optimized_fidelity = optimizer.estimate_fidelity(&optimized);
107 println!("Optimized circuit fidelity: {:.4}", optimized_fidelity);
108
109 println!("Available optimization passes:");
110 for pass in optimizer.get_passes() {
111 println!(" - {}", pass.name());
112 }
113
114 println!();
115 Ok(())
116}
117
118fn demo_noise_aware_cost_model(circuit: &Circuit<4>) -> quantrs2_core::error::QuantRS2Result<()> {
119 println!("--- Noise-Aware Cost Analysis ---");
120
121 let uniform_noise = NoiseModel::uniform(4);
122 let ibm_noise = NoiseModel::ibm_like(4);
123
124 let uniform_cost_model = NoiseAwareCostModel::new(uniform_noise);
125 let ibm_cost_model = NoiseAwareCostModel::new(ibm_noise);
126
127 let uniform_cost = uniform_cost_model.circuit_cost(circuit);
128 let ibm_cost = ibm_cost_model.circuit_cost(circuit);
129
130 println!("Circuit costs with different noise models:");
131 println!(" Uniform noise model: {:.2}", uniform_cost);
132 println!(" IBM-like noise model: {:.2}", ibm_cost);
133
134 // Analyze individual gate costs
135 println!("\nGate-by-gate cost analysis (IBM model):");
136 for (i, gate) in circuit.gates().iter().enumerate() {
137 let gate_cost = ibm_cost_model.gate_cost(gate.as_ref());
138 println!(" Gate {}: {} - Cost: {:.2}", i, gate.name(), gate_cost);
139 }
140
141 println!();
142 Ok(())
143}
144
145fn demo_noise_optimization_passes(
146 circuit: &Circuit<4>,
147) -> quantrs2_core::error::QuantRS2Result<()> {
148 println!("--- Individual Optimization Passes ---");
149
150 let noise_model = NoiseModel::ibm_like(4);
151 let coupling_map = CouplingMap::linear(4);
152
153 // Test coherence optimization
154 let coherence_opt = CoherenceOptimization::new(noise_model.clone());
155 let cost_model = NoiseAwareCostModel::new(noise_model.clone());
156
157 if coherence_opt.should_apply() {
158 let coherence_result = coherence_opt.apply(circuit, &cost_model)?;
159 println!("✓ Coherence optimization applied");
160 println!(" Original gates: {}", circuit.num_gates());
161 println!(" After coherence opt: {}", coherence_result.num_gates());
162 }
163
164 // Test noise-aware mapping
165 let mapping_opt = NoiseAwareMapping::new(noise_model.clone(), coupling_map.clone());
166 if mapping_opt.should_apply() {
167 let mapping_result = mapping_opt.apply(circuit, &cost_model)?;
168 println!("✓ Noise-aware mapping applied");
169 println!(" Original gates: {}", circuit.num_gates());
170 println!(" After mapping opt: {}", mapping_result.num_gates());
171 }
172
173 // Test dynamical decoupling
174 let dd_opt = DynamicalDecoupling::new(noise_model.clone());
175 if dd_opt.should_apply() {
176 let dd_result = dd_opt.apply(circuit, &cost_model)?;
177 println!("✓ Dynamical decoupling applied");
178 println!(" Original gates: {}", circuit.num_gates());
179 println!(" After DD insertion: {}", dd_result.num_gates());
180 }
181
182 println!();
183 Ok(())
184}
More examples
10fn main() -> quantrs2_core::error::QuantRS2Result<()> {
11 println!("=== Quantum Circuit Routing Demo ===\n");
12
13 // Create a test circuit with gates that require routing
14 let mut circuit = Circuit::<4>::new();
15
16 // Add gates that create connectivity issues on linear devices
17 circuit.add_gate(Hadamard { target: QubitId(0) })?;
18 circuit.add_gate(Hadamard { target: QubitId(1) })?;
19 circuit.add_gate(CNOT {
20 control: QubitId(0),
21 target: QubitId(3),
22 })?; // Non-adjacent!
23 circuit.add_gate(CNOT {
24 control: QubitId(1),
25 target: QubitId(2),
26 })?;
27 circuit.add_gate(CNOT {
28 control: QubitId(2),
29 target: QubitId(0),
30 })?; // Another non-adjacent!
31
32 println!("Original circuit:");
33 println!("H(0), H(1), CNOT(0,3), CNOT(1,2), CNOT(2,0)");
34 println!("Total gates: {}\n", circuit.num_gates());
35
36 // Test different coupling maps
37 demo_linear_coupling(&circuit)?;
38 demo_grid_coupling(&circuit)?;
39 demo_custom_device(&circuit)?;
40
41 Ok(())
42}
26fn demo_single_qubit_synthesis() -> quantrs2_core::error::QuantRS2Result<()> {
27 println!("--- Single-Qubit Unitary Synthesis ---");
28
29 let config = SynthesisConfig::default();
30 let synthesizer = SingleQubitSynthesizer::new(config);
31
32 // Test common single-qubit unitaries
33 let unitaries = vec![
34 ("Hadamard", hadamard()),
35 ("Pauli-X", pauli_x()),
36 ("Pauli-Y", pauli_y()),
37 ("Pauli-Z", pauli_z()),
38 ("RX(π/4)", rotation_x(PI / 4.0)),
39 ("RY(π/3)", rotation_y(PI / 3.0)),
40 ("RZ(π/2)", rotation_z(PI / 2.0)),
41 ];
42
43 for (name, unitary) in unitaries {
44 let circuit: Circuit<1> = synthesizer.synthesize(&unitary, QubitId(0))?;
45 println!("{:>12}: {} gates", name, circuit.num_gates());
46
47 // Show gate sequence for Hadamard as example
48 if name == "Hadamard" {
49 println!(" Gate sequence: ");
50 for (i, gate) in circuit.gates().iter().enumerate() {
51 println!(" {}: {}", i, gate.name());
52 }
53 }
54 }
55
56 println!();
57 Ok(())
58}
59
60fn demo_two_qubit_synthesis() -> quantrs2_core::error::QuantRS2Result<()> {
61 println!("--- Two-Qubit Unitary Synthesis ---");
62
63 let config = SynthesisConfig::default();
64 let synthesizer = TwoQubitSynthesizer::new(config);
65
66 // Test CNOT synthesis
67 let cnot_matrix = cnot();
68 let circuit: Circuit<2> = synthesizer.synthesize(&cnot_matrix, QubitId(0), QubitId(1))?;
69
70 println!("CNOT synthesis:");
71 println!(" Gates: {}", circuit.num_gates());
72 println!(" Gate sequence:");
73 for (i, gate) in circuit.gates().iter().enumerate() {
74 println!(" {}: {}", i, gate.name());
75 }
76
77 // Test controlled rotation
78 let theta = PI / 4.0;
79 println!("\nControlled RY(π/4) synthesis:");
80 let controlled_ry_circuit: Circuit<2> = synthesizer.cartan_decomposition(
81 &cnot_matrix, // Placeholder - would be actual controlled-RY matrix
82 QubitId(0),
83 QubitId(1),
84 )?;
85 println!(" Gates: {}", controlled_ry_circuit.num_gates());
86
87 println!();
88 Ok(())
89}
90
91fn demo_common_operations() -> quantrs2_core::error::QuantRS2Result<()> {
92 println!("--- Common Quantum Operations ---");
93
94 let synthesizer = UnitarySynthesizer::default_config();
95
96 // Quantum Fourier Transform
97 println!("Quantum Fourier Transform:");
98 for n_qubits in 2..=4 {
99 let qft_circuit: Circuit<4> = synthesizer.synthesize_qft(n_qubits)?;
100 println!(" QFT-{}: {} gates", n_qubits, qft_circuit.num_gates());
101 }
102
103 // Toffoli gate
104 let toffoli_circuit: Circuit<3> =
105 synthesizer.synthesize_toffoli(QubitId(0), QubitId(1), QubitId(2))?;
106 println!("\nToffoli gate: {} gates", toffoli_circuit.num_gates());
107
108 // Show first few gates of Toffoli decomposition
109 println!(" First 5 gates:");
110 for (i, gate) in toffoli_circuit.gates().iter().take(5).enumerate() {
111 println!(" {}: {}", i, gate.name());
112 }
113
114 println!();
115 Ok(())
116}
117
118fn demo_gate_sets() -> quantrs2_core::error::QuantRS2Result<()> {
119 println!("--- Different Gate Sets ---");
120
121 let gate_sets = vec![
122 ("Universal", GateSet::Universal),
123 ("IBM", GateSet::IBM),
124 ("Google", GateSet::Google),
125 ("Rigetti", GateSet::Rigetti),
126 ];
127
128 let hadamard_matrix = hadamard();
129
130 for (name, gate_set) in gate_sets {
131 let synthesizer = UnitarySynthesizer::for_gate_set(gate_set);
132
133 // For this demo, just show the configuration
134 println!("{} gate set configured", name);
135
136 // In a full implementation, would show different gate decompositions
137 // For now, all use the same underlying synthesis
138 let config = SynthesisConfig {
139 gate_set: synthesizer.config.gate_set.clone(),
140 ..Default::default()
141 };
142
143 println!(" Tolerance: {}", config.tolerance);
144 println!(" Max gates: {}", config.max_gates);
145 }
146
147 println!();
148 Ok(())
149}
150
151fn demo_validation() -> quantrs2_core::error::QuantRS2Result<()> {
152 println!("--- Unitary Matrix Validation ---");
153
154 let synthesizer = UnitarySynthesizer::default_config();
155
156 // Test valid unitaries
157 println!("Valid unitaries:");
158
159 let identity_2x2 = DMatrix::from_vec(
160 2,
161 2,
162 vec![
163 C64::new(1.0, 0.0),
164 C64::new(0.0, 0.0),
165 C64::new(0.0, 0.0),
166 C64::new(1.0, 0.0),
167 ],
168 );
169
170 match synthesizer.validate_unitary(&identity_2x2) {
171 Ok(_) => println!(" ✓ 2x2 Identity matrix"),
172 Err(e) => println!(" ✗ 2x2 Identity matrix: {}", e),
173 }
174
175 let hadamard_matrix = DMatrix::from_vec(
176 2,
177 2,
178 vec![
179 C64::new(1.0 / 2.0_f64.sqrt(), 0.0),
180 C64::new(1.0 / 2.0_f64.sqrt(), 0.0),
181 C64::new(1.0 / 2.0_f64.sqrt(), 0.0),
182 C64::new(-1.0 / 2.0_f64.sqrt(), 0.0),
183 ],
184 );
185
186 match synthesizer.validate_unitary(&hadamard_matrix) {
187 Ok(_) => println!(" ✓ Hadamard matrix"),
188 Err(e) => println!(" ✗ Hadamard matrix: {}", e),
189 }
190
191 // Test invalid unitaries
192 println!("\nInvalid unitaries:");
193
194 let non_square = DMatrix::from_vec(
195 2,
196 3,
197 vec![
198 C64::new(1.0, 0.0),
199 C64::new(0.0, 0.0),
200 C64::new(0.0, 0.0),
201 C64::new(0.0, 0.0),
202 C64::new(1.0, 0.0),
203 C64::new(0.0, 0.0),
204 ],
205 );
206
207 match synthesizer.validate_unitary(&non_square) {
208 Ok(_) => println!(" ✓ Non-square matrix (unexpected)"),
209 Err(_) => println!(" ✗ Non-square matrix (expected)"),
210 }
211
212 let non_unitary = DMatrix::from_vec(
213 2,
214 2,
215 vec![
216 C64::new(2.0, 0.0),
217 C64::new(0.0, 0.0),
218 C64::new(0.0, 0.0),
219 C64::new(1.0, 0.0),
220 ],
221 );
222
223 match synthesizer.validate_unitary(&non_unitary) {
224 Ok(_) => println!(" ✓ Non-unitary matrix (unexpected)"),
225 Err(_) => println!(" ✗ Non-unitary matrix (expected)"),
226 }
227
228 let wrong_dimension = DMatrix::from_vec(
229 3,
230 3,
231 vec![
232 C64::new(1.0, 0.0),
233 C64::new(0.0, 0.0),
234 C64::new(0.0, 0.0),
235 C64::new(0.0, 0.0),
236 C64::new(1.0, 0.0),
237 C64::new(0.0, 0.0),
238 C64::new(0.0, 0.0),
239 C64::new(0.0, 0.0),
240 C64::new(1.0, 0.0),
241 ],
242 );
243
244 match synthesizer.validate_unitary(&wrong_dimension) {
245 Ok(_) => println!(" ✓ Non-power-of-2 dimension (unexpected)"),
246 Err(_) => println!(" ✗ Non-power-of-2 dimension (expected)"),
247 }
248
249 println!();
250 Ok(())
251}
252
253fn demo_synthesis_comparison() -> quantrs2_core::error::QuantRS2Result<()> {
254 println!("--- Synthesis Algorithm Comparison ---");
255
256 let test_unitaries = vec![
257 ("Identity", DMatrix::identity(2, 2)),
258 (
259 "Hadamard",
260 DMatrix::from_vec(
261 2,
262 2,
263 vec![
264 C64::new(1.0 / 2.0_f64.sqrt(), 0.0),
265 C64::new(1.0 / 2.0_f64.sqrt(), 0.0),
266 C64::new(1.0 / 2.0_f64.sqrt(), 0.0),
267 C64::new(-1.0 / 2.0_f64.sqrt(), 0.0),
268 ],
269 ),
270 ),
271 (
272 "T gate",
273 DMatrix::from_vec(
274 2,
275 2,
276 vec![
277 C64::new(1.0, 0.0),
278 C64::new(0.0, 0.0),
279 C64::new(0.0, 0.0),
280 C64::from_polar(1.0, PI / 4.0),
281 ],
282 ),
283 ),
284 ];
285
286 let optimization_levels = vec![0, 1, 2, 3];
287
288 println!(
289 "{:<12} {:<8} {:<8} {:<8} {:<8}",
290 "Unitary", "Opt-0", "Opt-1", "Opt-2", "Opt-3"
291 );
292 println!("{:-<48}", "");
293
294 for (name, unitary) in test_unitaries {
295 print!("{:<12}", name);
296
297 for &opt_level in &optimization_levels {
298 let config = SynthesisConfig {
299 optimization_level: opt_level,
300 ..Default::default()
301 };
302
303 let synthesizer = UnitarySynthesizer::new(config);
304 match synthesizer.synthesize::<1>(&unitary) {
305 Ok(circuit) => print!(" {:<8}", circuit.num_gates()),
306 Err(_) => print!(" {:<8}", "Error"),
307 }
308 }
309 println!();
310 }
311
312 println!();
313 Ok(())
314}
63fn demo_circuit_compression() -> quantrs2_core::error::QuantRS2Result<()> {
64 println!("--- Circuit Compression ---");
65
66 // Create a circuit with repetitive structure
67 let mut circuit = Circuit::<4>::new();
68
69 // Add many gates
70 for i in 0..3 {
71 circuit.add_gate(Hadamard { target: QubitId(i) })?;
72 }
73
74 for i in 0..3 {
75 circuit.add_gate(CNOT {
76 control: QubitId(i),
77 target: QubitId(i + 1),
78 })?;
79 }
80
81 for i in 0..4 {
82 circuit.add_gate(T { target: QubitId(i) })?;
83 }
84
85 for i in (1..4).rev() {
86 circuit.add_gate(CNOT {
87 control: QubitId(i - 1),
88 target: QubitId(i),
89 })?;
90 }
91
92 println!("Original circuit: {} gates", circuit.num_gates());
93
94 // Compress using tensor networks
95 let compressor = TensorNetworkCompressor::new(16); // max bond dimension
96 let compressed = compressor.compress(&circuit)?;
97
98 println!(
99 "Compression ratio: {:.2}%",
100 compressed.compression_ratio() * 100.0
101 );
102
103 // Check fidelity
104 let fidelity = compressed.fidelity(&circuit)?;
105 println!("Fidelity with original: {:.6}", fidelity);
106
107 println!();
108 Ok(())
109}
110
111fn demo_mps_representation() -> quantrs2_core::error::QuantRS2Result<()> {
112 println!("--- Matrix Product State Representation ---");
113
114 // Create a circuit that generates an interesting entangled state
115 let mut circuit = Circuit::<6>::new();
116
117 // Create W state: (|100000⟩ + |010000⟩ + |001000⟩ + |000100⟩ + |000010⟩ + |000001⟩)/√6
118 circuit.add_gate(Hadamard { target: QubitId(0) })?;
119 circuit.add_gate(RotationZ {
120 target: QubitId(0),
121 theta: std::f64::consts::PI / 3.0,
122 })?;
123
124 for i in 0..5 {
125 circuit.add_gate(CNOT {
126 control: QubitId(i),
127 target: QubitId(i + 1),
128 })?;
129 }
130
131 println!("Created circuit for W state preparation");
132
133 // Convert to MPS
134 let mps = MatrixProductState::from_circuit(&circuit)?;
135 println!("Converted to MPS representation");
136
137 // Compress with different bond dimensions
138 let bond_dims = vec![2, 4, 8, 16];
139
140 for &max_bond in &bond_dims {
141 let mut mps_copy = MatrixProductState::from_circuit(&circuit)?;
142 mps_copy.compress(max_bond, 1e-10)?;
143
144 // In a real implementation, would calculate actual compression metrics
145 println!("Max bond dimension {}: compression successful", max_bond);
146 }
147
148 println!();
149 Ok(())
150}
151
152fn demo_compression_methods() -> quantrs2_core::error::QuantRS2Result<()> {
153 println!("--- Different Compression Methods ---");
154
155 let mut circuit = Circuit::<5>::new();
156
157 // Build a deep circuit
158 for _ in 0..5 {
159 for i in 0..5 {
160 circuit.add_gate(Hadamard { target: QubitId(i) })?;
161 }
162 for i in 0..4 {
163 circuit.add_gate(CNOT {
164 control: QubitId(i),
165 target: QubitId(i + 1),
166 })?;
167 }
168 }
169
170 println!("Built deep circuit with {} gates", circuit.num_gates());
171
172 // Test different compression methods
173 let methods = vec![
174 CompressionMethod::SVD,
175 CompressionMethod::DMRG,
176 CompressionMethod::TEBD,
177 ];
178
179 for method in methods {
180 let compressor = TensorNetworkCompressor::new(32).with_method(method.clone());
181
182 let compressed = compressor.compress(&circuit)?;
183
184 println!("\n{:?} compression:", method);
185 println!(
186 " Compression ratio: {:.2}%",
187 compressed.compression_ratio() * 100.0
188 );
189
190 // Try to decompress
191 let decompressed = compressed.decompress()?;
192 println!(" Decompressed to {} gates", decompressed.num_gates());
193 }
194
195 println!();
196 Ok(())
197}
198
199fn demo_tensor_contraction() -> quantrs2_core::error::QuantRS2Result<()> {
200 println!("--- Tensor Contraction Optimization ---");
201
202 // Create a circuit with specific structure
203 let mut circuit = Circuit::<4>::new();
204
205 // Layer 1: Single-qubit gates
206 for i in 0..4 {
207 circuit.add_gate(Hadamard { target: QubitId(i) })?;
208 }
209
210 // Layer 2: Entangling gates
211 circuit.add_gate(CNOT {
212 control: QubitId(0),
213 target: QubitId(1),
214 })?;
215 circuit.add_gate(CNOT {
216 control: QubitId(2),
217 target: QubitId(3),
218 })?;
219
220 // Layer 3: Cross entangling
221 circuit.add_gate(CNOT {
222 control: QubitId(1),
223 target: QubitId(2),
224 })?;
225
226 // Convert to tensor network
227 let converter = CircuitToTensorNetwork::<4>::new()
228 .with_max_bond_dim(8)
229 .with_tolerance(1e-12);
230
231 let tn = converter.convert(&circuit)?;
232
233 println!("Converted circuit to tensor network");
234 println!("Network has {} tensors", circuit.num_gates());
235
236 // Contract the network
237 let result = tn.contract_all()?;
238 println!("Contracted to single tensor of rank {}", result.rank());
239
240 println!();
241 Ok(())
242}
71fn demo_scheduling_strategies() -> quantrs2_core::error::QuantRS2Result<()> {
72 println!("--- Scheduling Strategies ---");
73
74 // Create a test circuit
75 let mut circuit = Circuit::<5>::new();
76
77 // Layer 1: Single-qubit gates
78 for i in 0..5 {
79 circuit.add_gate(Hadamard { target: QubitId(i) })?;
80 }
81
82 // Layer 2: Two-qubit gates
83 circuit.add_gate(CNOT {
84 control: QubitId(0),
85 target: QubitId(1),
86 })?;
87 circuit.add_gate(CNOT {
88 control: QubitId(2),
89 target: QubitId(3),
90 })?;
91 circuit.add_gate(CZ {
92 control: QubitId(1),
93 target: QubitId(2),
94 })?;
95
96 // Layer 3: More single-qubit gates
97 for i in 0..5 {
98 circuit.add_gate(RotationZ {
99 target: QubitId(i),
100 theta: std::f64::consts::PI / 4.0,
101 })?;
102 }
103
104 println!("Test circuit: {} gates on 5 qubits", circuit.num_gates());
105
106 let model = CrosstalkModel::uniform(5, 0.05);
107
108 // Strategy 1: Minimize crosstalk
109 let scheduler1 =
110 CrosstalkScheduler::new(model.clone()).with_strategy(SchedulingStrategy::MinimizeCrosstalk);
111
112 let schedule1 = scheduler1.schedule(&circuit)?;
113
114 println!("\nMinimize Crosstalk Strategy:");
115 println!(" Time slices: {}", schedule1.time_slices.len());
116 println!(" Total crosstalk: {:.4}", schedule1.total_crosstalk);
117 println!(" Execution time: {:.1} ns", schedule1.execution_time);
118
119 // Strategy 2: Minimize time with constraint
120 let scheduler2 =
121 CrosstalkScheduler::new(model.clone()).with_strategy(SchedulingStrategy::MinimizeTime {
122 max_crosstalk: 0.02,
123 });
124
125 let schedule2 = scheduler2.schedule(&circuit)?;
126
127 println!("\nMinimize Time Strategy (max crosstalk = 0.02):");
128 println!(" Time slices: {}", schedule2.time_slices.len());
129 println!(" Total crosstalk: {:.4}", schedule2.total_crosstalk);
130 println!(" Execution time: {:.1} ns", schedule2.execution_time);
131
132 // Strategy 3: Balanced
133 let scheduler3 = CrosstalkScheduler::new(model).with_strategy(SchedulingStrategy::Balanced {
134 time_weight: 0.5,
135 crosstalk_weight: 0.5,
136 });
137
138 let schedule3 = scheduler3.schedule(&circuit)?;
139
140 println!("\nBalanced Strategy:");
141 println!(" Time slices: {}", schedule3.time_slices.len());
142 println!(" Total crosstalk: {:.4}", schedule3.total_crosstalk);
143 println!(" Execution time: {:.1} ns", schedule3.execution_time);
144
145 // Show time slice details for first schedule
146 println!("\nTime slice details (MinimizeCrosstalk):");
147 for (i, slice) in schedule1.time_slices.iter().enumerate() {
148 println!(
149 " Slice {}: {} gates, max crosstalk = {:.4}, duration = {:.1} ns",
150 i,
151 slice.gates.len(),
152 slice.max_crosstalk,
153 slice.duration
154 );
155 }
156
157 println!();
158 Ok(())
159}
160
161fn demo_crosstalk_analysis() -> quantrs2_core::error::QuantRS2Result<()> {
162 println!("--- Cross-talk Analysis ---");
163
164 // Create a circuit with potential crosstalk issues
165 let mut circuit = Circuit::<6>::new();
166
167 // Parallel two-qubit gates on neighboring qubits
168 circuit.add_gate(CNOT {
169 control: QubitId(0),
170 target: QubitId(1),
171 })?;
172 circuit.add_gate(CNOT {
173 control: QubitId(2),
174 target: QubitId(3),
175 })?;
176 circuit.add_gate(CNOT {
177 control: QubitId(4),
178 target: QubitId(5),
179 })?;
180
181 // More gates that might have crosstalk
182 circuit.add_gate(CZ {
183 control: QubitId(1),
184 target: QubitId(2),
185 })?;
186 circuit.add_gate(CZ {
187 control: QubitId(3),
188 target: QubitId(4),
189 })?;
190
191 let model = CrosstalkModel::uniform(6, 0.05);
192 let analyzer = CrosstalkAnalyzer::new(model);
193
194 let analysis = analyzer.analyze(&circuit);
195
196 println!("Circuit analysis:");
197 println!(" Total gates: {}", analysis.total_gates);
198 println!(" Maximum crosstalk: {:.4}", analysis.max_crosstalk);
199 println!(" Problematic pairs: {}", analysis.problematic_pairs.len());
200
201 println!("\nTop problematic gate pairs:");
202 for (i, (g1, g2, crosstalk)) in analysis.problematic_pairs.iter().take(3).enumerate() {
203 println!(
204 " {}. Gates {} and {}: crosstalk = {:.4}",
205 i + 1,
206 g1,
207 g2,
208 crosstalk
209 );
210 }
211
212 // Get reordering suggestions
213 let suggestions = analyzer.suggest_reordering(&circuit)?;
214
215 println!("\nSuggested reorderings:");
216 for suggestion in suggestions.iter().take(3) {
217 println!(
218 " Move gates {} and {} apart: {}",
219 suggestion.gate1, suggestion.gate2, suggestion.reason
220 );
221 println!(
222 " Expected improvement: {:.4}",
223 suggestion.expected_improvement
224 );
225 }
226
227 println!();
228 Ok(())
229}
230
231fn demo_device_specific_scheduling() -> quantrs2_core::error::QuantRS2Result<()> {
232 println!("--- Device-Specific Scheduling ---");
233
234 // Create a realistic device characterization
235 let mut characterization = CrosstalkCharacterization {
236 measured_crosstalk: std::collections::HashMap::new(),
237 single_qubit_measurements: std::collections::HashMap::new(),
238 significance_threshold: 0.01,
239 device_coupling: vec![
240 (0, 1),
241 (1, 2),
242 (2, 3),
243 (3, 4), // Linear connectivity
244 (0, 5),
245 (1, 5),
246 (2, 5),
247 (3, 5),
248 (4, 5), // Star center at qubit 5
249 ],
250 };
251
252 // Add some measured crosstalk values
253 characterization
254 .single_qubit_measurements
255 .insert((0, 1), 0.02);
256 characterization
257 .single_qubit_measurements
258 .insert((1, 2), 0.02);
259 characterization
260 .single_qubit_measurements
261 .insert((0, 5), 0.03);
262 characterization
263 .single_qubit_measurements
264 .insert((1, 5), 0.03);
265
266 characterization
267 .measured_crosstalk
268 .insert(((0, 1), (2, 3)), 0.05);
269 characterization
270 .measured_crosstalk
271 .insert(((0, 1), (3, 4)), 0.02);
272 characterization
273 .measured_crosstalk
274 .insert(((0, 5), (1, 5)), 0.08);
275
276 let model = CrosstalkModel::from_characterization(&characterization);
277 let scheduler = CrosstalkScheduler::new(model);
278
279 // Create circuit that uses the device topology
280 let mut circuit = Circuit::<6>::new();
281
282 // Operations on linear chain
283 circuit.add_gate(Hadamard { target: QubitId(0) })?;
284 circuit.add_gate(CNOT {
285 control: QubitId(0),
286 target: QubitId(1),
287 })?;
288 circuit.add_gate(CNOT {
289 control: QubitId(1),
290 target: QubitId(2),
291 })?;
292
293 // Operations using star center
294 circuit.add_gate(Hadamard { target: QubitId(5) })?;
295 circuit.add_gate(CZ {
296 control: QubitId(5),
297 target: QubitId(0),
298 })?;
299 circuit.add_gate(CZ {
300 control: QubitId(5),
301 target: QubitId(3),
302 })?;
303
304 let schedule = scheduler.schedule(&circuit)?;
305
306 println!("Device-specific schedule:");
307 println!(" Device topology: Linear chain + star center");
308 println!(" Time slices: {}", schedule.time_slices.len());
309 println!(" Total crosstalk: {:.4}", schedule.total_crosstalk);
310
311 println!("\nSchedule details:");
312 for (i, slice) in schedule.time_slices.iter().enumerate() {
313 let gates = &circuit.gates();
314 print!(" Slice {}: ", i);
315 for &gate_idx in &slice.gates {
316 print!("{} ", gates[gate_idx].name());
317 }
318 println!("(crosstalk: {:.4})", slice.max_crosstalk);
319 }
320
321 println!();
322 Ok(())
323}
324
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}
8fn main() -> Result<(), Box<dyn std::error::Error>> {
9 println!("🧮 Variational Quantum Eigensolver (VQE) Demo");
10 println!("============================================\n");
11
12 // Example 1: Hardware-efficient ansatz for small molecules
13 println!("1. Hardware-Efficient Ansatz for 4-qubit system");
14 println!("-----------------------------------------------");
15
16 let mut vqe_circuit = VQECircuit::<4>::new(VQEAnsatz::HardwareEfficient { layers: 2 })?;
17 println!(
18 "Created VQE circuit with {} parameters",
19 vqe_circuit.num_parameters()
20 );
21
22 // Set some example parameters
23 let param_names = vqe_circuit.parameter_names.clone();
24 for (i, param_name) in param_names.iter().enumerate() {
25 vqe_circuit.set_parameter(param_name, 0.1 * i as f64)?;
26 }
27
28 println!("Set parameters: {:?}", vqe_circuit.parameters);
29 println!("Parameter names: {:?}\n", vqe_circuit.parameter_names);
30
31 // Example 2: UCCSD ansatz for quantum chemistry
32 println!("2. UCCSD Ansatz for quantum chemistry");
33 println!("--------------------------------------");
34
35 let uccsd_circuit = VQECircuit::<6>::new(VQEAnsatz::UCCSD {
36 occupied_orbitals: 2,
37 virtual_orbitals: 4,
38 })?;
39 println!(
40 "Created UCCSD circuit with {} parameters",
41 uccsd_circuit.num_parameters()
42 );
43 println!("Circuit has {} gates", uccsd_circuit.circuit.num_gates());
44
45 // Example 3: Observables for different Hamiltonians
46 println!("\n3. Creating Observables");
47 println!("----------------------");
48
49 // Heisenberg model
50 let heisenberg = VQEObservable::heisenberg_model(4, 1.0);
51 println!("Heisenberg model with {} terms", heisenberg.terms.len());
52
53 // Transverse Field Ising Model
54 let tfim = VQEObservable::tfim(4, 1.0, 0.5);
55 println!("TFIM model with {} terms", tfim.terms.len());
56
57 // Custom observable
58 let mut custom_obs = VQEObservable::new();
59 custom_obs.add_pauli_term(1.0, vec![(0, PauliOperator::Z), (1, PauliOperator::Z)]);
60 custom_obs.add_pauli_term(0.5, vec![(0, PauliOperator::X)]);
61 custom_obs.add_pauli_term(0.5, vec![(1, PauliOperator::X)]);
62 println!("Custom observable with {} terms", custom_obs.terms.len());
63
64 // Example 4: Custom ansatz construction
65 println!("\n4. Custom Ansatz Construction");
66 println!("-----------------------------");
67
68 let mut custom_vqe = VQECircuit::<3>::new(VQEAnsatz::Custom)?;
69
70 // Add custom parameterized gates
71 custom_vqe.add_parameterized_ry(Qubit(0), "theta_0")?;
72 custom_vqe.add_parameterized_rz(Qubit(1), "phi_1")?;
73 custom_vqe.add_parameterized_ry(Qubit(2), "theta_2")?;
74
75 // Add fixed gates to the underlying circuit
76 custom_vqe.circuit.cnot(Qubit(0), Qubit(1))?;
77 custom_vqe.circuit.cnot(Qubit(1), Qubit(2))?;
78
79 println!(
80 "Custom VQE circuit with {} parameters",
81 custom_vqe.num_parameters()
82 );
83
84 // Set parameter values
85 custom_vqe.set_parameter("theta_0", std::f64::consts::PI / 4.0)?;
86 custom_vqe.set_parameter("phi_1", std::f64::consts::PI / 2.0)?;
87 custom_vqe.set_parameter("theta_2", std::f64::consts::PI / 6.0)?;
88
89 println!(
90 "theta_0 = {:.4}",
91 custom_vqe.get_parameter("theta_0").unwrap()
92 );
93 println!("phi_1 = {:.4}", custom_vqe.get_parameter("phi_1").unwrap());
94 println!(
95 "theta_2 = {:.4}",
96 custom_vqe.get_parameter("theta_2").unwrap()
97 );
98
99 // Example 5: VQE Optimization (mock demonstration)
100 println!("\n5. VQE Optimization");
101 println!("-------------------");
102
103 let optimizer = VQEOptimizer::new(VQEOptimizerType::GradientDescent);
104 println!(
105 "Created optimizer with max iterations: {}",
106 optimizer.max_iterations
107 );
108 println!("Tolerance: {:.2e}", optimizer.tolerance);
109 println!("Learning rate: {}", optimizer.learning_rate);
110
111 // In a real implementation, this would actually optimize the parameters
112 let result = optimizer.optimize(&mut custom_vqe, &custom_obs)?;
113 println!("Optimization result:");
114 println!(" Ground state energy: {:.6}", result.ground_state_energy);
115 println!(" Converged: {}", result.converged);
116 println!(" Iterations: {}", result.iterations);
117 println!(" Gradient norm: {:.2e}", result.gradient_norm);
118
119 // Example 6: Different optimizer types
120 println!("\n6. Different Optimizer Types");
121 println!("----------------------------");
122
123 let optimizers = vec![
124 ("Gradient Descent", VQEOptimizerType::GradientDescent),
125 (
126 "Adam",
127 VQEOptimizerType::Adam {
128 beta1: 0.9,
129 beta2: 0.999,
130 },
131 ),
132 ("BFGS", VQEOptimizerType::BFGS),
133 ("Nelder-Mead", VQEOptimizerType::NelderMead),
134 (
135 "SPSA",
136 VQEOptimizerType::SPSA {
137 alpha: 0.602,
138 gamma: 0.101,
139 },
140 ),
141 ];
142
143 for (name, opt_type) in optimizers {
144 let opt = VQEOptimizer::new(opt_type);
145 println!(" {}: {:?}", name, opt.optimizer_type);
146 }
147
148 // Example 7: Real-space ansatz
149 println!("\n7. Real-Space Ansatz");
150 println!("--------------------");
151
152 let geometry = vec![
153 (0.0, 0.0, 0.0), // Site 0
154 (1.0, 0.0, 0.0), // Site 1
155 (0.0, 1.0, 0.0), // Site 2
156 (1.0, 1.0, 0.0), // Site 3
157 ];
158
159 let real_space_circuit = VQECircuit::<4>::new(VQEAnsatz::RealSpace { geometry })?;
160 println!(
161 "Real-space circuit with {} parameters",
162 real_space_circuit.num_parameters()
163 );
164 println!("Based on 2x2 square lattice geometry");
165
166 // Example 8: Molecular Hamiltonian
167 println!("\n8. Molecular Hamiltonian");
168 println!("------------------------");
169
170 // Example one-body and two-body integrals (simplified)
171 let one_body = vec![
172 (0, 0, -1.0), // h_00
173 (1, 1, -1.0), // h_11
174 (0, 1, -0.5), // h_01
175 ];
176
177 let two_body = vec![
178 (0, 1, 0, 1, 0.5), // (00|11)
179 (0, 0, 1, 1, 0.3), // (01|01)
180 ];
181
182 let molecular_ham = VQEObservable::molecular_hamiltonian(&one_body, &two_body);
183 println!(
184 "Molecular Hamiltonian with {} terms",
185 molecular_ham.terms.len()
186 );
187
188 println!("\n✅ VQE Demo completed successfully!");
189 println!("\nNote: This demo shows the VQE framework structure.");
190 println!("Real VQE optimization requires quantum simulation or hardware execution.");
191
192 Ok(())
193}
Sourcepub fn get_gate_names(&self) -> Vec<String>
pub fn get_gate_names(&self) -> Vec<String>
Get the names of all gates in the circuit
Sourcepub fn get_single_qubit_for_gate(
&self,
gate_type: &str,
index: usize,
) -> PyResult<u32>
pub fn get_single_qubit_for_gate( &self, gate_type: &str, index: usize, ) -> PyResult<u32>
Get a qubit for a specific single-qubit gate by gate type and index
Sourcepub fn get_rotation_params_for_gate(
&self,
gate_type: &str,
index: usize,
) -> PyResult<(u32, f64)>
pub fn get_rotation_params_for_gate( &self, gate_type: &str, index: usize, ) -> PyResult<(u32, f64)>
Get rotation parameters (qubit, angle) for a specific gate by gate type and index
Sourcepub fn get_two_qubit_params_for_gate(
&self,
gate_type: &str,
index: usize,
) -> PyResult<(u32, u32)>
pub fn get_two_qubit_params_for_gate( &self, gate_type: &str, index: usize, ) -> PyResult<(u32, u32)>
Get two-qubit parameters (control, target) for a specific gate by gate type and index
Sourcepub fn get_controlled_rotation_params_for_gate(
&self,
gate_type: &str,
index: usize,
) -> PyResult<(u32, u32, f64)>
pub fn get_controlled_rotation_params_for_gate( &self, gate_type: &str, index: usize, ) -> PyResult<(u32, u32, f64)>
Get controlled rotation parameters (control, target, angle) for a specific gate
Sourcepub fn get_three_qubit_params_for_gate(
&self,
gate_type: &str,
index: usize,
) -> PyResult<(u32, u32, u32)>
pub fn get_three_qubit_params_for_gate( &self, gate_type: &str, index: usize, ) -> PyResult<(u32, u32, u32)>
Get three-qubit parameters for gates like Toffoli or Fredkin
Sourcepub fn h(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self>
pub fn h(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self>
Apply a Hadamard gate to a qubit
Examples found in repository?
33fn create_sample_circuit() -> Circuit<4> {
34 // Create a circuit that has optimization opportunities
35 let mut circuit = Circuit::<4>::new();
36
37 // Add some gates with optimization opportunities
38 // Pattern 1: Redundant gates (H-H = I, X-X = I)
39 let _ = circuit.h(0);
40 let _ = circuit.h(0);
41
42 // Pattern 2: Commutable gates
43 let _ = circuit.x(1);
44 let _ = circuit.z(0);
45 let _ = circuit.cnot(0, 1);
46
47 // Pattern 3: Mergeable rotations
48 let _ = circuit.rz(2, std::f64::consts::PI / 4.0);
49 let _ = circuit.rz(2, std::f64::consts::PI / 4.0);
50
51 // Pattern 4: Known patterns (H-X-H = Z)
52 let _ = circuit.h(3);
53 let _ = circuit.x(3);
54 let _ = circuit.h(3);
55
56 // Pattern 5: Decomposable gates
57 let _ = circuit.toffoli(0, 1, 2);
58
59 circuit
60}
More examples
35fn demo_structural_equivalence() -> Result<(), Box<dyn std::error::Error>> {
36 println!("1. Structural Equivalence Check");
37 println!(" Checking if two circuits have identical gate sequences");
38
39 // Create two identical Bell state circuits
40 let mut circuit1 = Circuit::<2>::new();
41 circuit1.h(0)?;
42 circuit1.cnot(0, 1)?;
43
44 let mut circuit2 = Circuit::<2>::new();
45 circuit2.h(0)?;
46 circuit2.cnot(0, 1)?;
47
48 // Check structural equivalence
49 let checker = EquivalenceChecker::default();
50 let result = checker.check_structural_equivalence(&circuit1, &circuit2)?;
51
52 println!(" Circuit 1: H(0), CNOT(0,1)");
53 println!(" Circuit 2: H(0), CNOT(0,1)");
54 println!(" Structurally equivalent: {}", result.equivalent);
55 println!(" Details: {}", result.details);
56
57 Ok(())
58}
59
60/// Demonstrate algebraic equivalence (different gates, same result)
61fn demo_algebraic_equivalence() -> Result<(), Box<dyn std::error::Error>> {
62 println!("2. Algebraic Equivalence Check");
63 println!(" Different gate sequences that produce the same result");
64
65 // Circuit 1: X followed by X (should equal identity)
66 let mut circuit1 = Circuit::<1>::new();
67 circuit1.x(0)?;
68 circuit1.x(0)?;
69
70 // Circuit 2: Empty circuit (identity)
71 let circuit2 = Circuit::<1>::new();
72
73 // Check equivalence
74 let mut checker = EquivalenceChecker::default();
75 let result = checker.check_equivalence(&circuit1, &circuit2)?;
76
77 println!(" Circuit 1: X(0), X(0)");
78 println!(" Circuit 2: (empty)");
79 println!(" Equivalent: {}", result.equivalent);
80 println!(" Check type: {:?}", result.check_type);
81
82 // Another example: HZH = X
83 let mut circuit3 = Circuit::<1>::new();
84 circuit3.h(0)?;
85 circuit3.z(0)?;
86 circuit3.h(0)?;
87
88 let mut circuit4 = Circuit::<1>::new();
89 circuit4.x(0)?;
90
91 let result2 = checker.check_structural_equivalence(&circuit3, &circuit4)?;
92
93 println!("\n Circuit 3: H(0), Z(0), H(0)");
94 println!(" Circuit 4: X(0)");
95 println!(" Structurally equivalent: {}", result2.equivalent);
96 println!(" (Note: They are algebraically equivalent but not structurally)");
97
98 Ok(())
99}
100
101/// Demonstrate phase equivalence
102fn demo_phase_equivalence() -> Result<(), Box<dyn std::error::Error>> {
103 println!("3. Global Phase Equivalence");
104 println!(" Circuits that differ only by a global phase");
105
106 // Circuit 1: S gate (phase π/2)
107 let mut circuit1 = Circuit::<1>::new();
108 circuit1.s(0)?;
109
110 // Circuit 2: Z followed by T (phase π + π/4 = 5π/4)
111 // This gives the same result up to global phase
112 let mut circuit2 = Circuit::<1>::new();
113 circuit2.z(0)?;
114 circuit2.t(0)?;
115
116 // Check with phase ignored
117 let mut checker_phase = EquivalenceChecker::new(EquivalenceOptions {
118 tolerance: 1e-10,
119 ignore_global_phase: true,
120 check_all_states: true,
121 max_unitary_qubits: 10,
122 enable_adaptive_tolerance: true,
123 enable_statistical_analysis: true,
124 enable_stability_analysis: true,
125 enable_graph_comparison: false,
126 confidence_level: 0.95,
127 max_condition_number: 1e12,
128 scirs2_config: None,
129 complex_tolerance: 1e-14,
130 enable_parallel_computation: true,
131 });
132
133 // Check without phase ignored
134 let mut checker_no_phase = EquivalenceChecker::new(EquivalenceOptions {
135 tolerance: 1e-10,
136 ignore_global_phase: false,
137 check_all_states: true,
138 max_unitary_qubits: 10,
139 enable_adaptive_tolerance: true,
140 enable_statistical_analysis: true,
141 enable_stability_analysis: true,
142 enable_graph_comparison: false,
143 confidence_level: 0.95,
144 max_condition_number: 1e12,
145 scirs2_config: None,
146 complex_tolerance: 1e-14,
147 enable_parallel_computation: true,
148 });
149
150 println!(" Circuit 1: S(0)");
151 println!(" Circuit 2: Z(0), T(0)");
152
153 // Note: This example is simplified - actual phase relationship may differ
154 println!(" With global phase ignored: (would check if implemented)");
155 println!(" Without global phase: (would check if implemented)");
156
157 Ok(())
158}
159
160/// Demonstrate detection of non-equivalent circuits
161fn demo_non_equivalence() -> Result<(), Box<dyn std::error::Error>> {
162 println!("4. Non-Equivalence Detection");
163 println!(" Detecting when circuits are NOT equivalent");
164
165 // Circuit 1: Bell state |00> + |11>
166 let mut circuit1 = Circuit::<2>::new();
167 circuit1.h(0)?;
168 circuit1.cnot(0, 1)?;
169
170 // Circuit 2: Different entangled state |01> + |10>
171 let mut circuit2 = Circuit::<2>::new();
172 circuit2.h(0)?;
173 circuit2.x(1)?;
174 circuit2.cnot(0, 1)?;
175
176 let checker = EquivalenceChecker::default();
177 let result = checker.check_structural_equivalence(&circuit1, &circuit2)?;
178
179 println!(" Circuit 1: H(0), CNOT(0,1)");
180 println!(" Circuit 2: H(0), X(1), CNOT(0,1)");
181 println!(" Equivalent: {}", result.equivalent);
182 println!(" Details: {}", result.details);
183
184 Ok(())
185}
186
187/// Demonstrate custom tolerance settings
188fn demo_custom_tolerance() -> Result<(), Box<dyn std::error::Error>> {
189 println!("5. Custom Tolerance Settings");
190 println!(" Using different tolerance levels for approximate equivalence");
191
192 // Create circuits that might have small numerical differences
193 let mut circuit1 = Circuit::<1>::new();
194 circuit1.rx(0, PI / 4.0)?;
195
196 let mut circuit2 = Circuit::<1>::new();
197 circuit2.rx(0, PI / 4.0 + 1e-12)?; // Tiny difference
198
199 // Strict tolerance
200 let mut strict_checker = EquivalenceChecker::new(EquivalenceOptions {
201 tolerance: 1e-15,
202 ignore_global_phase: false,
203 check_all_states: true,
204 max_unitary_qubits: 10,
205 enable_adaptive_tolerance: true,
206 enable_statistical_analysis: true,
207 enable_stability_analysis: true,
208 enable_graph_comparison: false,
209 confidence_level: 0.95,
210 max_condition_number: 1e12,
211 scirs2_config: None,
212 complex_tolerance: 1e-14,
213 enable_parallel_computation: true,
214 });
215
216 // Relaxed tolerance
217 let mut relaxed_checker = EquivalenceChecker::new(EquivalenceOptions {
218 tolerance: 1e-10,
219 ignore_global_phase: false,
220 check_all_states: true,
221 max_unitary_qubits: 10,
222 enable_adaptive_tolerance: true,
223 enable_statistical_analysis: true,
224 enable_stability_analysis: true,
225 enable_graph_comparison: false,
226 confidence_level: 0.95,
227 max_condition_number: 1e12,
228 scirs2_config: None,
229 complex_tolerance: 1e-14,
230 enable_parallel_computation: true,
231 });
232
233 println!(" Circuit 1: RX(0, π/4)");
234 println!(" Circuit 2: RX(0, π/4 + 1e-12)");
235 println!(" With strict tolerance (1e-15): (would check if implemented)");
236 println!(" With relaxed tolerance (1e-10): (would check if implemented)");
237
238 Ok(())
239}
240
241/// Additional example: Verify circuit optimization preserves behavior
242fn verify_optimization_example() -> Result<(), Box<dyn std::error::Error>> {
243 println!("\nBonus: Verifying Circuit Optimization");
244
245 // Original circuit with redundant gates
246 let mut original = Circuit::<2>::new();
247 original.h(0)?;
248 original.cnot(0, 1)?;
249 original.cnot(0, 1)?; // This cancels the previous CNOT
250 original.h(0)?;
251
252 // Optimized circuit (manually optimized for this example)
253 let optimized = Circuit::<2>::new();
254 // Empty circuit since H-CNOT-CNOT-H = H-H = I
255
256 let checker = EquivalenceChecker::default();
257 println!(" Original: H(0), CNOT(0,1), CNOT(0,1), H(0)");
258 println!(" Optimized: (empty)");
259
260 // In practice, you would use the circuit optimizer and then verify:
261 // let optimized = original.optimize()?;
262 // let result = checker.check_equivalence(&original, &optimized)?;
263
264 Ok(())
265}
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}
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}
758fn create_test_jobs() -> Vec<DistributedJob<4>> {
759 let mut jobs = Vec::new();
760
761 // Job 1: Simple Bell state circuit
762 let mut bell_circuit = Circuit::<4>::new();
763 bell_circuit.h(Qubit(0)).unwrap();
764 bell_circuit.cnot(Qubit(0), Qubit(1)).unwrap();
765
766 jobs.push(DistributedJob {
767 id: "bell_state_job".to_string(),
768 circuit: bell_circuit,
769 parameters: ExecutionParameters {
770 shots: 1000,
771 optimization_level: 1,
772 error_mitigation: vec![ErrorMitigation::ReadoutErrorMitigation],
773 result_format: ResultFormat::Counts,
774 memory_requirement: None,
775 },
776 priority: Priority::Normal,
777 target_backends: None,
778 submitted_at: Instant::now(),
779 deadline: None,
780 });
781
782 // Job 2: GHZ state circuit
783 let mut ghz_circuit = Circuit::<4>::new();
784 ghz_circuit.h(Qubit(0)).unwrap();
785 ghz_circuit.cnot(Qubit(0), Qubit(1)).unwrap();
786 ghz_circuit.cnot(Qubit(1), Qubit(2)).unwrap();
787 ghz_circuit.cnot(Qubit(2), Qubit(3)).unwrap();
788
789 jobs.push(DistributedJob {
790 id: "ghz_state_job".to_string(),
791 circuit: ghz_circuit,
792 parameters: ExecutionParameters {
793 shots: 5000,
794 optimization_level: 2,
795 error_mitigation: vec![
796 ErrorMitigation::ReadoutErrorMitigation,
797 ErrorMitigation::ZeroNoiseExtrapolation,
798 ],
799 result_format: ResultFormat::Probabilities,
800 memory_requirement: Some(1.0), // 1 GB
801 },
802 priority: Priority::High,
803 target_backends: Some(vec![
804 "qiskit_aer_simulator".to_string(),
805 "aws_braket_sv1".to_string(),
806 ]),
807 submitted_at: Instant::now(),
808 deadline: Some(Instant::now() + std::time::Duration::from_secs(300)),
809 });
810
811 // Job 3: Variational circuit
812 let mut var_circuit = Circuit::<4>::new();
813 for i in 0..4 {
814 var_circuit.ry(Qubit(i), 0.5).unwrap();
815 }
816 for i in 0..3 {
817 var_circuit.cnot(Qubit(i), Qubit(i + 1)).unwrap();
818 }
819
820 jobs.push(DistributedJob {
821 id: "variational_job".to_string(),
822 circuit: var_circuit,
823 parameters: ExecutionParameters {
824 shots: 10000,
825 optimization_level: 3,
826 error_mitigation: vec![
827 ErrorMitigation::CliffordDataRegression,
828 ErrorMitigation::SymmetryVerification,
829 ],
830 result_format: ResultFormat::ExpectationValues,
831 memory_requirement: Some(2.0), // 2 GB
832 },
833 priority: Priority::Critical,
834 target_backends: None,
835 submitted_at: Instant::now(),
836 deadline: None,
837 });
838
839 jobs
840}
12fn main() -> Result<(), Box<dyn std::error::Error>> {
13 println!("🔄 Quantum-Classical Co-optimization Demo");
14 println!("=========================================\n");
15
16 // Example 1: Basic hybrid problem setup
17 println!("1. Setting up a Hybrid Optimization Problem");
18 println!("-------------------------------------------");
19
20 let mut problem = HybridOptimizationProblem::<4>::new();
21
22 // Set global parameters for the optimization
23 problem.set_global_parameters(vec![0.1, 0.2, 0.3, 0.4, 0.5, 0.6]);
24 println!("Set {} global parameters", problem.global_parameters.len());
25
26 // Create a quantum circuit component
27 let mut quantum_circuit = Circuit::<4>::new();
28 quantum_circuit.h(Qubit(0))?;
29 quantum_circuit.cnot(Qubit(0), Qubit(1))?;
30 quantum_circuit.ry(Qubit(2), 0.0)?; // Will be parameterized
31 quantum_circuit.cnot(Qubit(2), Qubit(3))?;
32
33 // Add quantum component to the problem
34 problem.add_quantum_component(
35 "quantum_processor".to_string(),
36 quantum_circuit,
37 vec![0, 1, 2], // Use parameters 0, 1, 2 from global parameter vector
38 )?;
39
40 println!(
41 "Added quantum circuit component with {} gates",
42 problem.quantum_circuits[0].circuit.num_gates()
43 );
44
45 // Example 2: Adding classical processing steps
46 println!("\n2. Adding Classical Processing Steps");
47 println!("-----------------------------------");
48
49 // Add a classical linear algebra step
50 problem.add_classical_step(
51 "matrix_operations".to_string(),
52 ClassicalStepType::LinearAlgebra(LinearAlgebraOp::MatrixMultiplication),
53 vec!["quantum_processor".to_string()],
54 vec!["processed_measurements".to_string()],
55 )?;
56
57 // Add a machine learning inference step
58 problem.add_classical_step(
59 "ml_inference".to_string(),
60 ClassicalStepType::MachineLearning(QCMLModelType::NeuralNetwork),
61 vec!["processed_measurements".to_string()],
62 vec!["ml_output".to_string()],
63 )?;
64
65 // Add a parameter update step
66 problem.add_classical_step(
67 "parameter_update".to_string(),
68 ClassicalStepType::ParameterUpdate(UpdateRule::AdamOptimizer),
69 vec!["ml_output".to_string()],
70 vec!["updated_parameters".to_string()],
71 )?;
72
73 println!(
74 "Added {} classical processing steps",
75 problem.classical_steps.len()
76 );
77
78 // Print details of each classical step
79 for (i, step) in problem.classical_steps.iter().enumerate() {
80 println!(" Step {}: {} ({:?})", i + 1, step.id, step.step_type);
81 }
82
83 // Example 3: Setting up data flow
84 println!("\n3. Setting up Data Flow");
85 println!("-----------------------");
86
87 // Connect quantum processor to matrix operations
88 problem.add_data_flow(
89 "quantum_processor".to_string(),
90 "matrix_operations".to_string(),
91 DataType::Measurements(vec![0.5, 0.3, 0.8, 0.1]),
92 )?;
93
94 // Connect matrix operations to ML inference
95 problem.add_data_flow(
96 "matrix_operations".to_string(),
97 "ml_inference".to_string(),
98 DataType::Matrix(vec![vec![1.0, 0.5], vec![0.3, 0.8]]),
99 )?;
100
101 // Connect ML inference to parameter update
102 problem.add_data_flow(
103 "ml_inference".to_string(),
104 "parameter_update".to_string(),
105 DataType::Scalar(0.75),
106 )?;
107
108 println!(
109 "Set up {} data flow connections",
110 problem.data_flow.edges.len()
111 );
112
113 // Print data flow details
114 for (i, (source, target, data_type)) in problem.data_flow.edges.iter().enumerate() {
115 println!(
116 " Flow {}: {} -> {} ({:?})",
117 i + 1,
118 source,
119 target,
120 data_type
121 );
122 }
123
124 // Example 4: Adding regularization
125 println!("\n4. Adding Regularization Terms");
126 println!("------------------------------");
127
128 // Add L2 regularization on parameters 0-2
129 problem.add_regularization(RegularizationType::L2, 0.01, vec![0, 1, 2])?;
130
131 // Add sparsity regularization on parameters 3-5
132 problem.add_regularization(RegularizationType::Sparsity, 0.005, vec![3, 4, 5])?;
133
134 println!(
135 "Added {} regularization terms",
136 problem.objective.regularization.len()
137 );
138
139 for (i, reg) in problem.objective.regularization.iter().enumerate() {
140 println!(
141 " Regularization {}: {:?} (strength: {:.3})",
142 i + 1,
143 reg.reg_type,
144 reg.strength
145 );
146 }
147
148 // Example 5: Validating the problem
149 println!("\n5. Problem Validation");
150 println!("---------------------");
151
152 match problem.validate() {
153 Ok(()) => println!("✅ Problem validation passed"),
154 Err(e) => println!("❌ Problem validation failed: {}", e),
155 }
156
157 println!("Total components: {}", problem.data_flow.nodes.len());
158 println!("Total connections: {}", problem.data_flow.edges.len());
159
160 // Example 6: Different optimization algorithms
161 println!("\n6. Optimization Algorithms");
162 println!("--------------------------");
163
164 let algorithms = vec![
165 (
166 "Coordinate Descent",
167 HybridOptimizationAlgorithm::CoordinateDescent,
168 ),
169 (
170 "Simultaneous Optimization",
171 HybridOptimizationAlgorithm::SimultaneousOptimization,
172 ),
173 (
174 "Hierarchical Optimization",
175 HybridOptimizationAlgorithm::HierarchicalOptimization,
176 ),
177 (
178 "Adaptive Optimization",
179 HybridOptimizationAlgorithm::AdaptiveOptimization,
180 ),
181 ];
182
183 for (name, algorithm) in algorithms {
184 let optimizer = HybridOptimizer::new(algorithm.clone());
185 println!(" {}: {:?}", name, optimizer.algorithm);
186 println!(" Max iterations: {}", optimizer.max_iterations);
187 println!(" Tolerance: {:.2e}", optimizer.tolerance);
188 println!(
189 " Initial learning rate: {}",
190 optimizer.learning_rate_schedule.initial_rate
191 );
192 }
193
194 // Example 7: Learning rate schedules
195 println!("\n7. Learning Rate Schedules");
196 println!("--------------------------");
197
198 let mut optimizer = HybridOptimizer::new(HybridOptimizationAlgorithm::SimultaneousOptimization);
199
200 // Set up different schedules
201 let schedules = vec![
202 ("Constant", ScheduleType::Constant),
203 ("Linear Decay", ScheduleType::LinearDecay),
204 ("Exponential Decay", ScheduleType::ExponentialDecay),
205 ("Step Decay", ScheduleType::StepDecay),
206 ("Cosine Annealing", ScheduleType::CosineAnnealing),
207 ];
208
209 for (name, schedule_type) in schedules {
210 optimizer.learning_rate_schedule.schedule_type = schedule_type.clone();
211 println!(" {}: {:?}", name, schedule_type);
212 }
213
214 // Example 8: Parallelization configuration
215 println!("\n8. Parallelization Configuration");
216 println!("--------------------------------");
217
218 optimizer.parallelization.quantum_parallelism = 4;
219 optimizer.parallelization.classical_parallelism = 8;
220 optimizer.parallelization.asynchronous = true;
221 optimizer.parallelization.load_balancing = LoadBalancingStrategy::WorkStealing;
222
223 println!(
224 "Quantum parallelism: {} circuits",
225 optimizer.parallelization.quantum_parallelism
226 );
227 println!(
228 "Classical parallelism: {} threads",
229 optimizer.parallelization.classical_parallelism
230 );
231 println!(
232 "Asynchronous execution: {}",
233 optimizer.parallelization.asynchronous
234 );
235 println!(
236 "Load balancing: {:?}",
237 optimizer.parallelization.load_balancing
238 );
239
240 // Example 9: Running optimization (mock)
241 println!("\n9. Running Optimization");
242 println!("-----------------------");
243
244 println!("Starting hybrid optimization...");
245 let result = optimizer.optimize(&mut problem)?;
246
247 println!("Optimization completed:");
248 println!(" Optimal value: {:.6}", result.optimal_value);
249 println!(" Converged: {}", result.converged);
250 println!(" Iterations: {}", result.iterations);
251 println!(" Final parameters: {:?}", result.optimal_parameters);
252
253 // Print some history information
254 if !result.history.objective_values.is_empty() {
255 println!(" Objective value history (first 5):");
256 for (i, &value) in result.history.objective_values.iter().take(5).enumerate() {
257 println!(" Iteration {}: {:.6}", i, value);
258 }
259 }
260
261 if !result.history.gradient_norms.is_empty() {
262 let final_gradient = result.history.gradient_norms.last().unwrap();
263 println!(" Final gradient norm: {:.2e}", final_gradient);
264 }
265
266 // Example 10: Specific hybrid algorithm patterns
267 println!("\n10. Common Hybrid Algorithm Patterns");
268 println!("------------------------------------");
269
270 // QAOA-like pattern
271 println!("QAOA-like pattern:");
272 println!(" 1. Prepare initial state (quantum)");
273 println!(" 2. Apply parameterized unitaries (quantum)");
274 println!(" 3. Measure expectation values (quantum)");
275 println!(" 4. Classical optimization step (classical)");
276 println!(" 5. Repeat until convergence");
277
278 // VQE with neural network pattern
279 println!("\nVQE with Neural Network pattern:");
280 println!(" 1. Prepare ansatz circuit (quantum)");
281 println!(" 2. Measure Pauli expectations (quantum)");
282 println!(" 3. Neural network post-processing (classical)");
283 println!(" 4. Gradient-based parameter update (classical)");
284 println!(" 5. Repeat until convergence");
285
286 // Quantum-enhanced ML pattern
287 println!("\nQuantum-enhanced ML pattern:");
288 println!(" 1. Classical feature encoding (classical)");
289 println!(" 2. Quantum feature mapping (quantum)");
290 println!(" 3. Quantum measurements (quantum)");
291 println!(" 4. Classical ML inference (classical)");
292 println!(" 5. End-to-end gradient updates (hybrid)");
293
294 // Example 11: Data types and flow
295 println!("\n11. Data Types in Hybrid Algorithms");
296 println!("-----------------------------------");
297
298 let data_types = vec![
299 (
300 "Quantum measurements",
301 "Raw measurement outcomes from quantum circuits",
302 ),
303 (
304 "Probability distributions",
305 "Estimated probability distributions from measurements",
306 ),
307 (
308 "Classical matrices",
309 "Processed data in matrix form for linear algebra",
310 ),
311 (
312 "Scalar values",
313 "Single numerical values like energies or costs",
314 ),
315 (
316 "Parameter vectors",
317 "Optimization parameters for both quantum and classical components",
318 ),
319 (
320 "Control signals",
321 "Boolean flags for adaptive algorithm control",
322 ),
323 ];
324
325 for (dtype, description) in data_types {
326 println!(" {}: {}", dtype, description);
327 }
328
329 println!("\n✅ Quantum-Classical Co-optimization Demo completed!");
330 println!("\nNote: This demo shows the framework structure for hybrid optimization.");
331 println!("Real co-optimization requires actual quantum and classical execution engines.");
332
333 Ok(())
334}
Sourcepub fn x(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self>
pub fn x(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self>
Apply a Pauli-X gate to a qubit
Examples found in repository?
33fn create_sample_circuit() -> Circuit<4> {
34 // Create a circuit that has optimization opportunities
35 let mut circuit = Circuit::<4>::new();
36
37 // Add some gates with optimization opportunities
38 // Pattern 1: Redundant gates (H-H = I, X-X = I)
39 let _ = circuit.h(0);
40 let _ = circuit.h(0);
41
42 // Pattern 2: Commutable gates
43 let _ = circuit.x(1);
44 let _ = circuit.z(0);
45 let _ = circuit.cnot(0, 1);
46
47 // Pattern 3: Mergeable rotations
48 let _ = circuit.rz(2, std::f64::consts::PI / 4.0);
49 let _ = circuit.rz(2, std::f64::consts::PI / 4.0);
50
51 // Pattern 4: Known patterns (H-X-H = Z)
52 let _ = circuit.h(3);
53 let _ = circuit.x(3);
54 let _ = circuit.h(3);
55
56 // Pattern 5: Decomposable gates
57 let _ = circuit.toffoli(0, 1, 2);
58
59 circuit
60}
More examples
61fn demo_algebraic_equivalence() -> Result<(), Box<dyn std::error::Error>> {
62 println!("2. Algebraic Equivalence Check");
63 println!(" Different gate sequences that produce the same result");
64
65 // Circuit 1: X followed by X (should equal identity)
66 let mut circuit1 = Circuit::<1>::new();
67 circuit1.x(0)?;
68 circuit1.x(0)?;
69
70 // Circuit 2: Empty circuit (identity)
71 let circuit2 = Circuit::<1>::new();
72
73 // Check equivalence
74 let mut checker = EquivalenceChecker::default();
75 let result = checker.check_equivalence(&circuit1, &circuit2)?;
76
77 println!(" Circuit 1: X(0), X(0)");
78 println!(" Circuit 2: (empty)");
79 println!(" Equivalent: {}", result.equivalent);
80 println!(" Check type: {:?}", result.check_type);
81
82 // Another example: HZH = X
83 let mut circuit3 = Circuit::<1>::new();
84 circuit3.h(0)?;
85 circuit3.z(0)?;
86 circuit3.h(0)?;
87
88 let mut circuit4 = Circuit::<1>::new();
89 circuit4.x(0)?;
90
91 let result2 = checker.check_structural_equivalence(&circuit3, &circuit4)?;
92
93 println!("\n Circuit 3: H(0), Z(0), H(0)");
94 println!(" Circuit 4: X(0)");
95 println!(" Structurally equivalent: {}", result2.equivalent);
96 println!(" (Note: They are algebraically equivalent but not structurally)");
97
98 Ok(())
99}
100
101/// Demonstrate phase equivalence
102fn demo_phase_equivalence() -> Result<(), Box<dyn std::error::Error>> {
103 println!("3. Global Phase Equivalence");
104 println!(" Circuits that differ only by a global phase");
105
106 // Circuit 1: S gate (phase π/2)
107 let mut circuit1 = Circuit::<1>::new();
108 circuit1.s(0)?;
109
110 // Circuit 2: Z followed by T (phase π + π/4 = 5π/4)
111 // This gives the same result up to global phase
112 let mut circuit2 = Circuit::<1>::new();
113 circuit2.z(0)?;
114 circuit2.t(0)?;
115
116 // Check with phase ignored
117 let mut checker_phase = EquivalenceChecker::new(EquivalenceOptions {
118 tolerance: 1e-10,
119 ignore_global_phase: true,
120 check_all_states: true,
121 max_unitary_qubits: 10,
122 enable_adaptive_tolerance: true,
123 enable_statistical_analysis: true,
124 enable_stability_analysis: true,
125 enable_graph_comparison: false,
126 confidence_level: 0.95,
127 max_condition_number: 1e12,
128 scirs2_config: None,
129 complex_tolerance: 1e-14,
130 enable_parallel_computation: true,
131 });
132
133 // Check without phase ignored
134 let mut checker_no_phase = EquivalenceChecker::new(EquivalenceOptions {
135 tolerance: 1e-10,
136 ignore_global_phase: false,
137 check_all_states: true,
138 max_unitary_qubits: 10,
139 enable_adaptive_tolerance: true,
140 enable_statistical_analysis: true,
141 enable_stability_analysis: true,
142 enable_graph_comparison: false,
143 confidence_level: 0.95,
144 max_condition_number: 1e12,
145 scirs2_config: None,
146 complex_tolerance: 1e-14,
147 enable_parallel_computation: true,
148 });
149
150 println!(" Circuit 1: S(0)");
151 println!(" Circuit 2: Z(0), T(0)");
152
153 // Note: This example is simplified - actual phase relationship may differ
154 println!(" With global phase ignored: (would check if implemented)");
155 println!(" Without global phase: (would check if implemented)");
156
157 Ok(())
158}
159
160/// Demonstrate detection of non-equivalent circuits
161fn demo_non_equivalence() -> Result<(), Box<dyn std::error::Error>> {
162 println!("4. Non-Equivalence Detection");
163 println!(" Detecting when circuits are NOT equivalent");
164
165 // Circuit 1: Bell state |00> + |11>
166 let mut circuit1 = Circuit::<2>::new();
167 circuit1.h(0)?;
168 circuit1.cnot(0, 1)?;
169
170 // Circuit 2: Different entangled state |01> + |10>
171 let mut circuit2 = Circuit::<2>::new();
172 circuit2.h(0)?;
173 circuit2.x(1)?;
174 circuit2.cnot(0, 1)?;
175
176 let checker = EquivalenceChecker::default();
177 let result = checker.check_structural_equivalence(&circuit1, &circuit2)?;
178
179 println!(" Circuit 1: H(0), CNOT(0,1)");
180 println!(" Circuit 2: H(0), X(1), CNOT(0,1)");
181 println!(" Equivalent: {}", result.equivalent);
182 println!(" Details: {}", result.details);
183
184 Ok(())
185}
Sourcepub fn y(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self>
pub fn y(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self>
Apply a Pauli-Y gate to a qubit
Sourcepub fn z(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self>
pub fn z(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self>
Apply a Pauli-Z gate to a qubit
Examples found in repository?
33fn create_sample_circuit() -> Circuit<4> {
34 // Create a circuit that has optimization opportunities
35 let mut circuit = Circuit::<4>::new();
36
37 // Add some gates with optimization opportunities
38 // Pattern 1: Redundant gates (H-H = I, X-X = I)
39 let _ = circuit.h(0);
40 let _ = circuit.h(0);
41
42 // Pattern 2: Commutable gates
43 let _ = circuit.x(1);
44 let _ = circuit.z(0);
45 let _ = circuit.cnot(0, 1);
46
47 // Pattern 3: Mergeable rotations
48 let _ = circuit.rz(2, std::f64::consts::PI / 4.0);
49 let _ = circuit.rz(2, std::f64::consts::PI / 4.0);
50
51 // Pattern 4: Known patterns (H-X-H = Z)
52 let _ = circuit.h(3);
53 let _ = circuit.x(3);
54 let _ = circuit.h(3);
55
56 // Pattern 5: Decomposable gates
57 let _ = circuit.toffoli(0, 1, 2);
58
59 circuit
60}
More examples
61fn demo_algebraic_equivalence() -> Result<(), Box<dyn std::error::Error>> {
62 println!("2. Algebraic Equivalence Check");
63 println!(" Different gate sequences that produce the same result");
64
65 // Circuit 1: X followed by X (should equal identity)
66 let mut circuit1 = Circuit::<1>::new();
67 circuit1.x(0)?;
68 circuit1.x(0)?;
69
70 // Circuit 2: Empty circuit (identity)
71 let circuit2 = Circuit::<1>::new();
72
73 // Check equivalence
74 let mut checker = EquivalenceChecker::default();
75 let result = checker.check_equivalence(&circuit1, &circuit2)?;
76
77 println!(" Circuit 1: X(0), X(0)");
78 println!(" Circuit 2: (empty)");
79 println!(" Equivalent: {}", result.equivalent);
80 println!(" Check type: {:?}", result.check_type);
81
82 // Another example: HZH = X
83 let mut circuit3 = Circuit::<1>::new();
84 circuit3.h(0)?;
85 circuit3.z(0)?;
86 circuit3.h(0)?;
87
88 let mut circuit4 = Circuit::<1>::new();
89 circuit4.x(0)?;
90
91 let result2 = checker.check_structural_equivalence(&circuit3, &circuit4)?;
92
93 println!("\n Circuit 3: H(0), Z(0), H(0)");
94 println!(" Circuit 4: X(0)");
95 println!(" Structurally equivalent: {}", result2.equivalent);
96 println!(" (Note: They are algebraically equivalent but not structurally)");
97
98 Ok(())
99}
100
101/// Demonstrate phase equivalence
102fn demo_phase_equivalence() -> Result<(), Box<dyn std::error::Error>> {
103 println!("3. Global Phase Equivalence");
104 println!(" Circuits that differ only by a global phase");
105
106 // Circuit 1: S gate (phase π/2)
107 let mut circuit1 = Circuit::<1>::new();
108 circuit1.s(0)?;
109
110 // Circuit 2: Z followed by T (phase π + π/4 = 5π/4)
111 // This gives the same result up to global phase
112 let mut circuit2 = Circuit::<1>::new();
113 circuit2.z(0)?;
114 circuit2.t(0)?;
115
116 // Check with phase ignored
117 let mut checker_phase = EquivalenceChecker::new(EquivalenceOptions {
118 tolerance: 1e-10,
119 ignore_global_phase: true,
120 check_all_states: true,
121 max_unitary_qubits: 10,
122 enable_adaptive_tolerance: true,
123 enable_statistical_analysis: true,
124 enable_stability_analysis: true,
125 enable_graph_comparison: false,
126 confidence_level: 0.95,
127 max_condition_number: 1e12,
128 scirs2_config: None,
129 complex_tolerance: 1e-14,
130 enable_parallel_computation: true,
131 });
132
133 // Check without phase ignored
134 let mut checker_no_phase = EquivalenceChecker::new(EquivalenceOptions {
135 tolerance: 1e-10,
136 ignore_global_phase: false,
137 check_all_states: true,
138 max_unitary_qubits: 10,
139 enable_adaptive_tolerance: true,
140 enable_statistical_analysis: true,
141 enable_stability_analysis: true,
142 enable_graph_comparison: false,
143 confidence_level: 0.95,
144 max_condition_number: 1e12,
145 scirs2_config: None,
146 complex_tolerance: 1e-14,
147 enable_parallel_computation: true,
148 });
149
150 println!(" Circuit 1: S(0)");
151 println!(" Circuit 2: Z(0), T(0)");
152
153 // Note: This example is simplified - actual phase relationship may differ
154 println!(" With global phase ignored: (would check if implemented)");
155 println!(" Without global phase: (would check if implemented)");
156
157 Ok(())
158}
Sourcepub fn rx(
&mut self,
target: impl Into<QubitId>,
theta: f64,
) -> QuantRS2Result<&mut Self>
pub fn rx( &mut self, target: impl Into<QubitId>, theta: f64, ) -> QuantRS2Result<&mut Self>
Apply a rotation around X-axis
Examples found in repository?
188fn demo_custom_tolerance() -> Result<(), Box<dyn std::error::Error>> {
189 println!("5. Custom Tolerance Settings");
190 println!(" Using different tolerance levels for approximate equivalence");
191
192 // Create circuits that might have small numerical differences
193 let mut circuit1 = Circuit::<1>::new();
194 circuit1.rx(0, PI / 4.0)?;
195
196 let mut circuit2 = Circuit::<1>::new();
197 circuit2.rx(0, PI / 4.0 + 1e-12)?; // Tiny difference
198
199 // Strict tolerance
200 let mut strict_checker = EquivalenceChecker::new(EquivalenceOptions {
201 tolerance: 1e-15,
202 ignore_global_phase: false,
203 check_all_states: true,
204 max_unitary_qubits: 10,
205 enable_adaptive_tolerance: true,
206 enable_statistical_analysis: true,
207 enable_stability_analysis: true,
208 enable_graph_comparison: false,
209 confidence_level: 0.95,
210 max_condition_number: 1e12,
211 scirs2_config: None,
212 complex_tolerance: 1e-14,
213 enable_parallel_computation: true,
214 });
215
216 // Relaxed tolerance
217 let mut relaxed_checker = EquivalenceChecker::new(EquivalenceOptions {
218 tolerance: 1e-10,
219 ignore_global_phase: false,
220 check_all_states: true,
221 max_unitary_qubits: 10,
222 enable_adaptive_tolerance: true,
223 enable_statistical_analysis: true,
224 enable_stability_analysis: true,
225 enable_graph_comparison: false,
226 confidence_level: 0.95,
227 max_condition_number: 1e12,
228 scirs2_config: None,
229 complex_tolerance: 1e-14,
230 enable_parallel_computation: true,
231 });
232
233 println!(" Circuit 1: RX(0, π/4)");
234 println!(" Circuit 2: RX(0, π/4 + 1e-12)");
235 println!(" With strict tolerance (1e-15): (would check if implemented)");
236 println!(" With relaxed tolerance (1e-10): (would check if implemented)");
237
238 Ok(())
239}
More examples
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}
Sourcepub fn ry(
&mut self,
target: impl Into<QubitId>,
theta: f64,
) -> QuantRS2Result<&mut Self>
pub fn ry( &mut self, target: impl Into<QubitId>, theta: f64, ) -> QuantRS2Result<&mut Self>
Apply a rotation around Y-axis
Examples found in repository?
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}
More examples
758fn create_test_jobs() -> Vec<DistributedJob<4>> {
759 let mut jobs = Vec::new();
760
761 // Job 1: Simple Bell state circuit
762 let mut bell_circuit = Circuit::<4>::new();
763 bell_circuit.h(Qubit(0)).unwrap();
764 bell_circuit.cnot(Qubit(0), Qubit(1)).unwrap();
765
766 jobs.push(DistributedJob {
767 id: "bell_state_job".to_string(),
768 circuit: bell_circuit,
769 parameters: ExecutionParameters {
770 shots: 1000,
771 optimization_level: 1,
772 error_mitigation: vec![ErrorMitigation::ReadoutErrorMitigation],
773 result_format: ResultFormat::Counts,
774 memory_requirement: None,
775 },
776 priority: Priority::Normal,
777 target_backends: None,
778 submitted_at: Instant::now(),
779 deadline: None,
780 });
781
782 // Job 2: GHZ state circuit
783 let mut ghz_circuit = Circuit::<4>::new();
784 ghz_circuit.h(Qubit(0)).unwrap();
785 ghz_circuit.cnot(Qubit(0), Qubit(1)).unwrap();
786 ghz_circuit.cnot(Qubit(1), Qubit(2)).unwrap();
787 ghz_circuit.cnot(Qubit(2), Qubit(3)).unwrap();
788
789 jobs.push(DistributedJob {
790 id: "ghz_state_job".to_string(),
791 circuit: ghz_circuit,
792 parameters: ExecutionParameters {
793 shots: 5000,
794 optimization_level: 2,
795 error_mitigation: vec![
796 ErrorMitigation::ReadoutErrorMitigation,
797 ErrorMitigation::ZeroNoiseExtrapolation,
798 ],
799 result_format: ResultFormat::Probabilities,
800 memory_requirement: Some(1.0), // 1 GB
801 },
802 priority: Priority::High,
803 target_backends: Some(vec![
804 "qiskit_aer_simulator".to_string(),
805 "aws_braket_sv1".to_string(),
806 ]),
807 submitted_at: Instant::now(),
808 deadline: Some(Instant::now() + std::time::Duration::from_secs(300)),
809 });
810
811 // Job 3: Variational circuit
812 let mut var_circuit = Circuit::<4>::new();
813 for i in 0..4 {
814 var_circuit.ry(Qubit(i), 0.5).unwrap();
815 }
816 for i in 0..3 {
817 var_circuit.cnot(Qubit(i), Qubit(i + 1)).unwrap();
818 }
819
820 jobs.push(DistributedJob {
821 id: "variational_job".to_string(),
822 circuit: var_circuit,
823 parameters: ExecutionParameters {
824 shots: 10000,
825 optimization_level: 3,
826 error_mitigation: vec![
827 ErrorMitigation::CliffordDataRegression,
828 ErrorMitigation::SymmetryVerification,
829 ],
830 result_format: ResultFormat::ExpectationValues,
831 memory_requirement: Some(2.0), // 2 GB
832 },
833 priority: Priority::Critical,
834 target_backends: None,
835 submitted_at: Instant::now(),
836 deadline: None,
837 });
838
839 jobs
840}
12fn main() -> Result<(), Box<dyn std::error::Error>> {
13 println!("🔄 Quantum-Classical Co-optimization Demo");
14 println!("=========================================\n");
15
16 // Example 1: Basic hybrid problem setup
17 println!("1. Setting up a Hybrid Optimization Problem");
18 println!("-------------------------------------------");
19
20 let mut problem = HybridOptimizationProblem::<4>::new();
21
22 // Set global parameters for the optimization
23 problem.set_global_parameters(vec![0.1, 0.2, 0.3, 0.4, 0.5, 0.6]);
24 println!("Set {} global parameters", problem.global_parameters.len());
25
26 // Create a quantum circuit component
27 let mut quantum_circuit = Circuit::<4>::new();
28 quantum_circuit.h(Qubit(0))?;
29 quantum_circuit.cnot(Qubit(0), Qubit(1))?;
30 quantum_circuit.ry(Qubit(2), 0.0)?; // Will be parameterized
31 quantum_circuit.cnot(Qubit(2), Qubit(3))?;
32
33 // Add quantum component to the problem
34 problem.add_quantum_component(
35 "quantum_processor".to_string(),
36 quantum_circuit,
37 vec![0, 1, 2], // Use parameters 0, 1, 2 from global parameter vector
38 )?;
39
40 println!(
41 "Added quantum circuit component with {} gates",
42 problem.quantum_circuits[0].circuit.num_gates()
43 );
44
45 // Example 2: Adding classical processing steps
46 println!("\n2. Adding Classical Processing Steps");
47 println!("-----------------------------------");
48
49 // Add a classical linear algebra step
50 problem.add_classical_step(
51 "matrix_operations".to_string(),
52 ClassicalStepType::LinearAlgebra(LinearAlgebraOp::MatrixMultiplication),
53 vec!["quantum_processor".to_string()],
54 vec!["processed_measurements".to_string()],
55 )?;
56
57 // Add a machine learning inference step
58 problem.add_classical_step(
59 "ml_inference".to_string(),
60 ClassicalStepType::MachineLearning(QCMLModelType::NeuralNetwork),
61 vec!["processed_measurements".to_string()],
62 vec!["ml_output".to_string()],
63 )?;
64
65 // Add a parameter update step
66 problem.add_classical_step(
67 "parameter_update".to_string(),
68 ClassicalStepType::ParameterUpdate(UpdateRule::AdamOptimizer),
69 vec!["ml_output".to_string()],
70 vec!["updated_parameters".to_string()],
71 )?;
72
73 println!(
74 "Added {} classical processing steps",
75 problem.classical_steps.len()
76 );
77
78 // Print details of each classical step
79 for (i, step) in problem.classical_steps.iter().enumerate() {
80 println!(" Step {}: {} ({:?})", i + 1, step.id, step.step_type);
81 }
82
83 // Example 3: Setting up data flow
84 println!("\n3. Setting up Data Flow");
85 println!("-----------------------");
86
87 // Connect quantum processor to matrix operations
88 problem.add_data_flow(
89 "quantum_processor".to_string(),
90 "matrix_operations".to_string(),
91 DataType::Measurements(vec![0.5, 0.3, 0.8, 0.1]),
92 )?;
93
94 // Connect matrix operations to ML inference
95 problem.add_data_flow(
96 "matrix_operations".to_string(),
97 "ml_inference".to_string(),
98 DataType::Matrix(vec![vec![1.0, 0.5], vec![0.3, 0.8]]),
99 )?;
100
101 // Connect ML inference to parameter update
102 problem.add_data_flow(
103 "ml_inference".to_string(),
104 "parameter_update".to_string(),
105 DataType::Scalar(0.75),
106 )?;
107
108 println!(
109 "Set up {} data flow connections",
110 problem.data_flow.edges.len()
111 );
112
113 // Print data flow details
114 for (i, (source, target, data_type)) in problem.data_flow.edges.iter().enumerate() {
115 println!(
116 " Flow {}: {} -> {} ({:?})",
117 i + 1,
118 source,
119 target,
120 data_type
121 );
122 }
123
124 // Example 4: Adding regularization
125 println!("\n4. Adding Regularization Terms");
126 println!("------------------------------");
127
128 // Add L2 regularization on parameters 0-2
129 problem.add_regularization(RegularizationType::L2, 0.01, vec![0, 1, 2])?;
130
131 // Add sparsity regularization on parameters 3-5
132 problem.add_regularization(RegularizationType::Sparsity, 0.005, vec![3, 4, 5])?;
133
134 println!(
135 "Added {} regularization terms",
136 problem.objective.regularization.len()
137 );
138
139 for (i, reg) in problem.objective.regularization.iter().enumerate() {
140 println!(
141 " Regularization {}: {:?} (strength: {:.3})",
142 i + 1,
143 reg.reg_type,
144 reg.strength
145 );
146 }
147
148 // Example 5: Validating the problem
149 println!("\n5. Problem Validation");
150 println!("---------------------");
151
152 match problem.validate() {
153 Ok(()) => println!("✅ Problem validation passed"),
154 Err(e) => println!("❌ Problem validation failed: {}", e),
155 }
156
157 println!("Total components: {}", problem.data_flow.nodes.len());
158 println!("Total connections: {}", problem.data_flow.edges.len());
159
160 // Example 6: Different optimization algorithms
161 println!("\n6. Optimization Algorithms");
162 println!("--------------------------");
163
164 let algorithms = vec![
165 (
166 "Coordinate Descent",
167 HybridOptimizationAlgorithm::CoordinateDescent,
168 ),
169 (
170 "Simultaneous Optimization",
171 HybridOptimizationAlgorithm::SimultaneousOptimization,
172 ),
173 (
174 "Hierarchical Optimization",
175 HybridOptimizationAlgorithm::HierarchicalOptimization,
176 ),
177 (
178 "Adaptive Optimization",
179 HybridOptimizationAlgorithm::AdaptiveOptimization,
180 ),
181 ];
182
183 for (name, algorithm) in algorithms {
184 let optimizer = HybridOptimizer::new(algorithm.clone());
185 println!(" {}: {:?}", name, optimizer.algorithm);
186 println!(" Max iterations: {}", optimizer.max_iterations);
187 println!(" Tolerance: {:.2e}", optimizer.tolerance);
188 println!(
189 " Initial learning rate: {}",
190 optimizer.learning_rate_schedule.initial_rate
191 );
192 }
193
194 // Example 7: Learning rate schedules
195 println!("\n7. Learning Rate Schedules");
196 println!("--------------------------");
197
198 let mut optimizer = HybridOptimizer::new(HybridOptimizationAlgorithm::SimultaneousOptimization);
199
200 // Set up different schedules
201 let schedules = vec![
202 ("Constant", ScheduleType::Constant),
203 ("Linear Decay", ScheduleType::LinearDecay),
204 ("Exponential Decay", ScheduleType::ExponentialDecay),
205 ("Step Decay", ScheduleType::StepDecay),
206 ("Cosine Annealing", ScheduleType::CosineAnnealing),
207 ];
208
209 for (name, schedule_type) in schedules {
210 optimizer.learning_rate_schedule.schedule_type = schedule_type.clone();
211 println!(" {}: {:?}", name, schedule_type);
212 }
213
214 // Example 8: Parallelization configuration
215 println!("\n8. Parallelization Configuration");
216 println!("--------------------------------");
217
218 optimizer.parallelization.quantum_parallelism = 4;
219 optimizer.parallelization.classical_parallelism = 8;
220 optimizer.parallelization.asynchronous = true;
221 optimizer.parallelization.load_balancing = LoadBalancingStrategy::WorkStealing;
222
223 println!(
224 "Quantum parallelism: {} circuits",
225 optimizer.parallelization.quantum_parallelism
226 );
227 println!(
228 "Classical parallelism: {} threads",
229 optimizer.parallelization.classical_parallelism
230 );
231 println!(
232 "Asynchronous execution: {}",
233 optimizer.parallelization.asynchronous
234 );
235 println!(
236 "Load balancing: {:?}",
237 optimizer.parallelization.load_balancing
238 );
239
240 // Example 9: Running optimization (mock)
241 println!("\n9. Running Optimization");
242 println!("-----------------------");
243
244 println!("Starting hybrid optimization...");
245 let result = optimizer.optimize(&mut problem)?;
246
247 println!("Optimization completed:");
248 println!(" Optimal value: {:.6}", result.optimal_value);
249 println!(" Converged: {}", result.converged);
250 println!(" Iterations: {}", result.iterations);
251 println!(" Final parameters: {:?}", result.optimal_parameters);
252
253 // Print some history information
254 if !result.history.objective_values.is_empty() {
255 println!(" Objective value history (first 5):");
256 for (i, &value) in result.history.objective_values.iter().take(5).enumerate() {
257 println!(" Iteration {}: {:.6}", i, value);
258 }
259 }
260
261 if !result.history.gradient_norms.is_empty() {
262 let final_gradient = result.history.gradient_norms.last().unwrap();
263 println!(" Final gradient norm: {:.2e}", final_gradient);
264 }
265
266 // Example 10: Specific hybrid algorithm patterns
267 println!("\n10. Common Hybrid Algorithm Patterns");
268 println!("------------------------------------");
269
270 // QAOA-like pattern
271 println!("QAOA-like pattern:");
272 println!(" 1. Prepare initial state (quantum)");
273 println!(" 2. Apply parameterized unitaries (quantum)");
274 println!(" 3. Measure expectation values (quantum)");
275 println!(" 4. Classical optimization step (classical)");
276 println!(" 5. Repeat until convergence");
277
278 // VQE with neural network pattern
279 println!("\nVQE with Neural Network pattern:");
280 println!(" 1. Prepare ansatz circuit (quantum)");
281 println!(" 2. Measure Pauli expectations (quantum)");
282 println!(" 3. Neural network post-processing (classical)");
283 println!(" 4. Gradient-based parameter update (classical)");
284 println!(" 5. Repeat until convergence");
285
286 // Quantum-enhanced ML pattern
287 println!("\nQuantum-enhanced ML pattern:");
288 println!(" 1. Classical feature encoding (classical)");
289 println!(" 2. Quantum feature mapping (quantum)");
290 println!(" 3. Quantum measurements (quantum)");
291 println!(" 4. Classical ML inference (classical)");
292 println!(" 5. End-to-end gradient updates (hybrid)");
293
294 // Example 11: Data types and flow
295 println!("\n11. Data Types in Hybrid Algorithms");
296 println!("-----------------------------------");
297
298 let data_types = vec![
299 (
300 "Quantum measurements",
301 "Raw measurement outcomes from quantum circuits",
302 ),
303 (
304 "Probability distributions",
305 "Estimated probability distributions from measurements",
306 ),
307 (
308 "Classical matrices",
309 "Processed data in matrix form for linear algebra",
310 ),
311 (
312 "Scalar values",
313 "Single numerical values like energies or costs",
314 ),
315 (
316 "Parameter vectors",
317 "Optimization parameters for both quantum and classical components",
318 ),
319 (
320 "Control signals",
321 "Boolean flags for adaptive algorithm control",
322 ),
323 ];
324
325 for (dtype, description) in data_types {
326 println!(" {}: {}", dtype, description);
327 }
328
329 println!("\n✅ Quantum-Classical Co-optimization Demo completed!");
330 println!("\nNote: This demo shows the framework structure for hybrid optimization.");
331 println!("Real co-optimization requires actual quantum and classical execution engines.");
332
333 Ok(())
334}
Sourcepub fn rz(
&mut self,
target: impl Into<QubitId>,
theta: f64,
) -> QuantRS2Result<&mut Self>
pub fn rz( &mut self, target: impl Into<QubitId>, theta: f64, ) -> QuantRS2Result<&mut Self>
Apply a rotation around Z-axis
Examples found in repository?
33fn create_sample_circuit() -> Circuit<4> {
34 // Create a circuit that has optimization opportunities
35 let mut circuit = Circuit::<4>::new();
36
37 // Add some gates with optimization opportunities
38 // Pattern 1: Redundant gates (H-H = I, X-X = I)
39 let _ = circuit.h(0);
40 let _ = circuit.h(0);
41
42 // Pattern 2: Commutable gates
43 let _ = circuit.x(1);
44 let _ = circuit.z(0);
45 let _ = circuit.cnot(0, 1);
46
47 // Pattern 3: Mergeable rotations
48 let _ = circuit.rz(2, std::f64::consts::PI / 4.0);
49 let _ = circuit.rz(2, std::f64::consts::PI / 4.0);
50
51 // Pattern 4: Known patterns (H-X-H = Z)
52 let _ = circuit.h(3);
53 let _ = circuit.x(3);
54 let _ = circuit.h(3);
55
56 // Pattern 5: Decomposable gates
57 let _ = circuit.toffoli(0, 1, 2);
58
59 circuit
60}
More examples
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}
Sourcepub fn s(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self>
pub fn s(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self>
Apply a Phase gate (S gate)
Examples found in repository?
102fn demo_phase_equivalence() -> Result<(), Box<dyn std::error::Error>> {
103 println!("3. Global Phase Equivalence");
104 println!(" Circuits that differ only by a global phase");
105
106 // Circuit 1: S gate (phase π/2)
107 let mut circuit1 = Circuit::<1>::new();
108 circuit1.s(0)?;
109
110 // Circuit 2: Z followed by T (phase π + π/4 = 5π/4)
111 // This gives the same result up to global phase
112 let mut circuit2 = Circuit::<1>::new();
113 circuit2.z(0)?;
114 circuit2.t(0)?;
115
116 // Check with phase ignored
117 let mut checker_phase = EquivalenceChecker::new(EquivalenceOptions {
118 tolerance: 1e-10,
119 ignore_global_phase: true,
120 check_all_states: true,
121 max_unitary_qubits: 10,
122 enable_adaptive_tolerance: true,
123 enable_statistical_analysis: true,
124 enable_stability_analysis: true,
125 enable_graph_comparison: false,
126 confidence_level: 0.95,
127 max_condition_number: 1e12,
128 scirs2_config: None,
129 complex_tolerance: 1e-14,
130 enable_parallel_computation: true,
131 });
132
133 // Check without phase ignored
134 let mut checker_no_phase = EquivalenceChecker::new(EquivalenceOptions {
135 tolerance: 1e-10,
136 ignore_global_phase: false,
137 check_all_states: true,
138 max_unitary_qubits: 10,
139 enable_adaptive_tolerance: true,
140 enable_statistical_analysis: true,
141 enable_stability_analysis: true,
142 enable_graph_comparison: false,
143 confidence_level: 0.95,
144 max_condition_number: 1e12,
145 scirs2_config: None,
146 complex_tolerance: 1e-14,
147 enable_parallel_computation: true,
148 });
149
150 println!(" Circuit 1: S(0)");
151 println!(" Circuit 2: Z(0), T(0)");
152
153 // Note: This example is simplified - actual phase relationship may differ
154 println!(" With global phase ignored: (would check if implemented)");
155 println!(" Without global phase: (would check if implemented)");
156
157 Ok(())
158}
Sourcepub fn sdg(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self>
pub fn sdg(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self>
Apply a Phase-dagger gate (S† gate)
Sourcepub fn t(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self>
pub fn t(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self>
Apply a T gate
Examples found in repository?
102fn demo_phase_equivalence() -> Result<(), Box<dyn std::error::Error>> {
103 println!("3. Global Phase Equivalence");
104 println!(" Circuits that differ only by a global phase");
105
106 // Circuit 1: S gate (phase π/2)
107 let mut circuit1 = Circuit::<1>::new();
108 circuit1.s(0)?;
109
110 // Circuit 2: Z followed by T (phase π + π/4 = 5π/4)
111 // This gives the same result up to global phase
112 let mut circuit2 = Circuit::<1>::new();
113 circuit2.z(0)?;
114 circuit2.t(0)?;
115
116 // Check with phase ignored
117 let mut checker_phase = EquivalenceChecker::new(EquivalenceOptions {
118 tolerance: 1e-10,
119 ignore_global_phase: true,
120 check_all_states: true,
121 max_unitary_qubits: 10,
122 enable_adaptive_tolerance: true,
123 enable_statistical_analysis: true,
124 enable_stability_analysis: true,
125 enable_graph_comparison: false,
126 confidence_level: 0.95,
127 max_condition_number: 1e12,
128 scirs2_config: None,
129 complex_tolerance: 1e-14,
130 enable_parallel_computation: true,
131 });
132
133 // Check without phase ignored
134 let mut checker_no_phase = EquivalenceChecker::new(EquivalenceOptions {
135 tolerance: 1e-10,
136 ignore_global_phase: false,
137 check_all_states: true,
138 max_unitary_qubits: 10,
139 enable_adaptive_tolerance: true,
140 enable_statistical_analysis: true,
141 enable_stability_analysis: true,
142 enable_graph_comparison: false,
143 confidence_level: 0.95,
144 max_condition_number: 1e12,
145 scirs2_config: None,
146 complex_tolerance: 1e-14,
147 enable_parallel_computation: true,
148 });
149
150 println!(" Circuit 1: S(0)");
151 println!(" Circuit 2: Z(0), T(0)");
152
153 // Note: This example is simplified - actual phase relationship may differ
154 println!(" With global phase ignored: (would check if implemented)");
155 println!(" Without global phase: (would check if implemented)");
156
157 Ok(())
158}
Sourcepub fn tdg(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self>
pub fn tdg(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self>
Apply a T-dagger gate (T† gate)
Sourcepub fn sx(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self>
pub fn sx(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self>
Apply a Square Root of X gate (√X)
Sourcepub fn sxdg(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self>
pub fn sxdg(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self>
Apply a Square Root of X Dagger gate (√X†)
Sourcepub fn cnot(
&mut self,
control: impl Into<QubitId>,
target: impl Into<QubitId>,
) -> QuantRS2Result<&mut Self>
pub fn cnot( &mut self, control: impl Into<QubitId>, target: impl Into<QubitId>, ) -> QuantRS2Result<&mut Self>
Apply a CNOT gate
Examples found in repository?
33fn create_sample_circuit() -> Circuit<4> {
34 // Create a circuit that has optimization opportunities
35 let mut circuit = Circuit::<4>::new();
36
37 // Add some gates with optimization opportunities
38 // Pattern 1: Redundant gates (H-H = I, X-X = I)
39 let _ = circuit.h(0);
40 let _ = circuit.h(0);
41
42 // Pattern 2: Commutable gates
43 let _ = circuit.x(1);
44 let _ = circuit.z(0);
45 let _ = circuit.cnot(0, 1);
46
47 // Pattern 3: Mergeable rotations
48 let _ = circuit.rz(2, std::f64::consts::PI / 4.0);
49 let _ = circuit.rz(2, std::f64::consts::PI / 4.0);
50
51 // Pattern 4: Known patterns (H-X-H = Z)
52 let _ = circuit.h(3);
53 let _ = circuit.x(3);
54 let _ = circuit.h(3);
55
56 // Pattern 5: Decomposable gates
57 let _ = circuit.toffoli(0, 1, 2);
58
59 circuit
60}
More examples
35fn demo_structural_equivalence() -> Result<(), Box<dyn std::error::Error>> {
36 println!("1. Structural Equivalence Check");
37 println!(" Checking if two circuits have identical gate sequences");
38
39 // Create two identical Bell state circuits
40 let mut circuit1 = Circuit::<2>::new();
41 circuit1.h(0)?;
42 circuit1.cnot(0, 1)?;
43
44 let mut circuit2 = Circuit::<2>::new();
45 circuit2.h(0)?;
46 circuit2.cnot(0, 1)?;
47
48 // Check structural equivalence
49 let checker = EquivalenceChecker::default();
50 let result = checker.check_structural_equivalence(&circuit1, &circuit2)?;
51
52 println!(" Circuit 1: H(0), CNOT(0,1)");
53 println!(" Circuit 2: H(0), CNOT(0,1)");
54 println!(" Structurally equivalent: {}", result.equivalent);
55 println!(" Details: {}", result.details);
56
57 Ok(())
58}
59
60/// Demonstrate algebraic equivalence (different gates, same result)
61fn demo_algebraic_equivalence() -> Result<(), Box<dyn std::error::Error>> {
62 println!("2. Algebraic Equivalence Check");
63 println!(" Different gate sequences that produce the same result");
64
65 // Circuit 1: X followed by X (should equal identity)
66 let mut circuit1 = Circuit::<1>::new();
67 circuit1.x(0)?;
68 circuit1.x(0)?;
69
70 // Circuit 2: Empty circuit (identity)
71 let circuit2 = Circuit::<1>::new();
72
73 // Check equivalence
74 let mut checker = EquivalenceChecker::default();
75 let result = checker.check_equivalence(&circuit1, &circuit2)?;
76
77 println!(" Circuit 1: X(0), X(0)");
78 println!(" Circuit 2: (empty)");
79 println!(" Equivalent: {}", result.equivalent);
80 println!(" Check type: {:?}", result.check_type);
81
82 // Another example: HZH = X
83 let mut circuit3 = Circuit::<1>::new();
84 circuit3.h(0)?;
85 circuit3.z(0)?;
86 circuit3.h(0)?;
87
88 let mut circuit4 = Circuit::<1>::new();
89 circuit4.x(0)?;
90
91 let result2 = checker.check_structural_equivalence(&circuit3, &circuit4)?;
92
93 println!("\n Circuit 3: H(0), Z(0), H(0)");
94 println!(" Circuit 4: X(0)");
95 println!(" Structurally equivalent: {}", result2.equivalent);
96 println!(" (Note: They are algebraically equivalent but not structurally)");
97
98 Ok(())
99}
100
101/// Demonstrate phase equivalence
102fn demo_phase_equivalence() -> Result<(), Box<dyn std::error::Error>> {
103 println!("3. Global Phase Equivalence");
104 println!(" Circuits that differ only by a global phase");
105
106 // Circuit 1: S gate (phase π/2)
107 let mut circuit1 = Circuit::<1>::new();
108 circuit1.s(0)?;
109
110 // Circuit 2: Z followed by T (phase π + π/4 = 5π/4)
111 // This gives the same result up to global phase
112 let mut circuit2 = Circuit::<1>::new();
113 circuit2.z(0)?;
114 circuit2.t(0)?;
115
116 // Check with phase ignored
117 let mut checker_phase = EquivalenceChecker::new(EquivalenceOptions {
118 tolerance: 1e-10,
119 ignore_global_phase: true,
120 check_all_states: true,
121 max_unitary_qubits: 10,
122 enable_adaptive_tolerance: true,
123 enable_statistical_analysis: true,
124 enable_stability_analysis: true,
125 enable_graph_comparison: false,
126 confidence_level: 0.95,
127 max_condition_number: 1e12,
128 scirs2_config: None,
129 complex_tolerance: 1e-14,
130 enable_parallel_computation: true,
131 });
132
133 // Check without phase ignored
134 let mut checker_no_phase = EquivalenceChecker::new(EquivalenceOptions {
135 tolerance: 1e-10,
136 ignore_global_phase: false,
137 check_all_states: true,
138 max_unitary_qubits: 10,
139 enable_adaptive_tolerance: true,
140 enable_statistical_analysis: true,
141 enable_stability_analysis: true,
142 enable_graph_comparison: false,
143 confidence_level: 0.95,
144 max_condition_number: 1e12,
145 scirs2_config: None,
146 complex_tolerance: 1e-14,
147 enable_parallel_computation: true,
148 });
149
150 println!(" Circuit 1: S(0)");
151 println!(" Circuit 2: Z(0), T(0)");
152
153 // Note: This example is simplified - actual phase relationship may differ
154 println!(" With global phase ignored: (would check if implemented)");
155 println!(" Without global phase: (would check if implemented)");
156
157 Ok(())
158}
159
160/// Demonstrate detection of non-equivalent circuits
161fn demo_non_equivalence() -> Result<(), Box<dyn std::error::Error>> {
162 println!("4. Non-Equivalence Detection");
163 println!(" Detecting when circuits are NOT equivalent");
164
165 // Circuit 1: Bell state |00> + |11>
166 let mut circuit1 = Circuit::<2>::new();
167 circuit1.h(0)?;
168 circuit1.cnot(0, 1)?;
169
170 // Circuit 2: Different entangled state |01> + |10>
171 let mut circuit2 = Circuit::<2>::new();
172 circuit2.h(0)?;
173 circuit2.x(1)?;
174 circuit2.cnot(0, 1)?;
175
176 let checker = EquivalenceChecker::default();
177 let result = checker.check_structural_equivalence(&circuit1, &circuit2)?;
178
179 println!(" Circuit 1: H(0), CNOT(0,1)");
180 println!(" Circuit 2: H(0), X(1), CNOT(0,1)");
181 println!(" Equivalent: {}", result.equivalent);
182 println!(" Details: {}", result.details);
183
184 Ok(())
185}
186
187/// Demonstrate custom tolerance settings
188fn demo_custom_tolerance() -> Result<(), Box<dyn std::error::Error>> {
189 println!("5. Custom Tolerance Settings");
190 println!(" Using different tolerance levels for approximate equivalence");
191
192 // Create circuits that might have small numerical differences
193 let mut circuit1 = Circuit::<1>::new();
194 circuit1.rx(0, PI / 4.0)?;
195
196 let mut circuit2 = Circuit::<1>::new();
197 circuit2.rx(0, PI / 4.0 + 1e-12)?; // Tiny difference
198
199 // Strict tolerance
200 let mut strict_checker = EquivalenceChecker::new(EquivalenceOptions {
201 tolerance: 1e-15,
202 ignore_global_phase: false,
203 check_all_states: true,
204 max_unitary_qubits: 10,
205 enable_adaptive_tolerance: true,
206 enable_statistical_analysis: true,
207 enable_stability_analysis: true,
208 enable_graph_comparison: false,
209 confidence_level: 0.95,
210 max_condition_number: 1e12,
211 scirs2_config: None,
212 complex_tolerance: 1e-14,
213 enable_parallel_computation: true,
214 });
215
216 // Relaxed tolerance
217 let mut relaxed_checker = EquivalenceChecker::new(EquivalenceOptions {
218 tolerance: 1e-10,
219 ignore_global_phase: false,
220 check_all_states: true,
221 max_unitary_qubits: 10,
222 enable_adaptive_tolerance: true,
223 enable_statistical_analysis: true,
224 enable_stability_analysis: true,
225 enable_graph_comparison: false,
226 confidence_level: 0.95,
227 max_condition_number: 1e12,
228 scirs2_config: None,
229 complex_tolerance: 1e-14,
230 enable_parallel_computation: true,
231 });
232
233 println!(" Circuit 1: RX(0, π/4)");
234 println!(" Circuit 2: RX(0, π/4 + 1e-12)");
235 println!(" With strict tolerance (1e-15): (would check if implemented)");
236 println!(" With relaxed tolerance (1e-10): (would check if implemented)");
237
238 Ok(())
239}
240
241/// Additional example: Verify circuit optimization preserves behavior
242fn verify_optimization_example() -> Result<(), Box<dyn std::error::Error>> {
243 println!("\nBonus: Verifying Circuit Optimization");
244
245 // Original circuit with redundant gates
246 let mut original = Circuit::<2>::new();
247 original.h(0)?;
248 original.cnot(0, 1)?;
249 original.cnot(0, 1)?; // This cancels the previous CNOT
250 original.h(0)?;
251
252 // Optimized circuit (manually optimized for this example)
253 let optimized = Circuit::<2>::new();
254 // Empty circuit since H-CNOT-CNOT-H = H-H = I
255
256 let checker = EquivalenceChecker::default();
257 println!(" Original: H(0), CNOT(0,1), CNOT(0,1), H(0)");
258 println!(" Optimized: (empty)");
259
260 // In practice, you would use the circuit optimizer and then verify:
261 // let optimized = original.optimize()?;
262 // let result = checker.check_equivalence(&original, &optimized)?;
263
264 Ok(())
265}
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}
758fn create_test_jobs() -> Vec<DistributedJob<4>> {
759 let mut jobs = Vec::new();
760
761 // Job 1: Simple Bell state circuit
762 let mut bell_circuit = Circuit::<4>::new();
763 bell_circuit.h(Qubit(0)).unwrap();
764 bell_circuit.cnot(Qubit(0), Qubit(1)).unwrap();
765
766 jobs.push(DistributedJob {
767 id: "bell_state_job".to_string(),
768 circuit: bell_circuit,
769 parameters: ExecutionParameters {
770 shots: 1000,
771 optimization_level: 1,
772 error_mitigation: vec![ErrorMitigation::ReadoutErrorMitigation],
773 result_format: ResultFormat::Counts,
774 memory_requirement: None,
775 },
776 priority: Priority::Normal,
777 target_backends: None,
778 submitted_at: Instant::now(),
779 deadline: None,
780 });
781
782 // Job 2: GHZ state circuit
783 let mut ghz_circuit = Circuit::<4>::new();
784 ghz_circuit.h(Qubit(0)).unwrap();
785 ghz_circuit.cnot(Qubit(0), Qubit(1)).unwrap();
786 ghz_circuit.cnot(Qubit(1), Qubit(2)).unwrap();
787 ghz_circuit.cnot(Qubit(2), Qubit(3)).unwrap();
788
789 jobs.push(DistributedJob {
790 id: "ghz_state_job".to_string(),
791 circuit: ghz_circuit,
792 parameters: ExecutionParameters {
793 shots: 5000,
794 optimization_level: 2,
795 error_mitigation: vec![
796 ErrorMitigation::ReadoutErrorMitigation,
797 ErrorMitigation::ZeroNoiseExtrapolation,
798 ],
799 result_format: ResultFormat::Probabilities,
800 memory_requirement: Some(1.0), // 1 GB
801 },
802 priority: Priority::High,
803 target_backends: Some(vec![
804 "qiskit_aer_simulator".to_string(),
805 "aws_braket_sv1".to_string(),
806 ]),
807 submitted_at: Instant::now(),
808 deadline: Some(Instant::now() + std::time::Duration::from_secs(300)),
809 });
810
811 // Job 3: Variational circuit
812 let mut var_circuit = Circuit::<4>::new();
813 for i in 0..4 {
814 var_circuit.ry(Qubit(i), 0.5).unwrap();
815 }
816 for i in 0..3 {
817 var_circuit.cnot(Qubit(i), Qubit(i + 1)).unwrap();
818 }
819
820 jobs.push(DistributedJob {
821 id: "variational_job".to_string(),
822 circuit: var_circuit,
823 parameters: ExecutionParameters {
824 shots: 10000,
825 optimization_level: 3,
826 error_mitigation: vec![
827 ErrorMitigation::CliffordDataRegression,
828 ErrorMitigation::SymmetryVerification,
829 ],
830 result_format: ResultFormat::ExpectationValues,
831 memory_requirement: Some(2.0), // 2 GB
832 },
833 priority: Priority::Critical,
834 target_backends: None,
835 submitted_at: Instant::now(),
836 deadline: None,
837 });
838
839 jobs
840}
8fn main() -> Result<(), Box<dyn std::error::Error>> {
9 println!("🧮 Variational Quantum Eigensolver (VQE) Demo");
10 println!("============================================\n");
11
12 // Example 1: Hardware-efficient ansatz for small molecules
13 println!("1. Hardware-Efficient Ansatz for 4-qubit system");
14 println!("-----------------------------------------------");
15
16 let mut vqe_circuit = VQECircuit::<4>::new(VQEAnsatz::HardwareEfficient { layers: 2 })?;
17 println!(
18 "Created VQE circuit with {} parameters",
19 vqe_circuit.num_parameters()
20 );
21
22 // Set some example parameters
23 let param_names = vqe_circuit.parameter_names.clone();
24 for (i, param_name) in param_names.iter().enumerate() {
25 vqe_circuit.set_parameter(param_name, 0.1 * i as f64)?;
26 }
27
28 println!("Set parameters: {:?}", vqe_circuit.parameters);
29 println!("Parameter names: {:?}\n", vqe_circuit.parameter_names);
30
31 // Example 2: UCCSD ansatz for quantum chemistry
32 println!("2. UCCSD Ansatz for quantum chemistry");
33 println!("--------------------------------------");
34
35 let uccsd_circuit = VQECircuit::<6>::new(VQEAnsatz::UCCSD {
36 occupied_orbitals: 2,
37 virtual_orbitals: 4,
38 })?;
39 println!(
40 "Created UCCSD circuit with {} parameters",
41 uccsd_circuit.num_parameters()
42 );
43 println!("Circuit has {} gates", uccsd_circuit.circuit.num_gates());
44
45 // Example 3: Observables for different Hamiltonians
46 println!("\n3. Creating Observables");
47 println!("----------------------");
48
49 // Heisenberg model
50 let heisenberg = VQEObservable::heisenberg_model(4, 1.0);
51 println!("Heisenberg model with {} terms", heisenberg.terms.len());
52
53 // Transverse Field Ising Model
54 let tfim = VQEObservable::tfim(4, 1.0, 0.5);
55 println!("TFIM model with {} terms", tfim.terms.len());
56
57 // Custom observable
58 let mut custom_obs = VQEObservable::new();
59 custom_obs.add_pauli_term(1.0, vec![(0, PauliOperator::Z), (1, PauliOperator::Z)]);
60 custom_obs.add_pauli_term(0.5, vec![(0, PauliOperator::X)]);
61 custom_obs.add_pauli_term(0.5, vec![(1, PauliOperator::X)]);
62 println!("Custom observable with {} terms", custom_obs.terms.len());
63
64 // Example 4: Custom ansatz construction
65 println!("\n4. Custom Ansatz Construction");
66 println!("-----------------------------");
67
68 let mut custom_vqe = VQECircuit::<3>::new(VQEAnsatz::Custom)?;
69
70 // Add custom parameterized gates
71 custom_vqe.add_parameterized_ry(Qubit(0), "theta_0")?;
72 custom_vqe.add_parameterized_rz(Qubit(1), "phi_1")?;
73 custom_vqe.add_parameterized_ry(Qubit(2), "theta_2")?;
74
75 // Add fixed gates to the underlying circuit
76 custom_vqe.circuit.cnot(Qubit(0), Qubit(1))?;
77 custom_vqe.circuit.cnot(Qubit(1), Qubit(2))?;
78
79 println!(
80 "Custom VQE circuit with {} parameters",
81 custom_vqe.num_parameters()
82 );
83
84 // Set parameter values
85 custom_vqe.set_parameter("theta_0", std::f64::consts::PI / 4.0)?;
86 custom_vqe.set_parameter("phi_1", std::f64::consts::PI / 2.0)?;
87 custom_vqe.set_parameter("theta_2", std::f64::consts::PI / 6.0)?;
88
89 println!(
90 "theta_0 = {:.4}",
91 custom_vqe.get_parameter("theta_0").unwrap()
92 );
93 println!("phi_1 = {:.4}", custom_vqe.get_parameter("phi_1").unwrap());
94 println!(
95 "theta_2 = {:.4}",
96 custom_vqe.get_parameter("theta_2").unwrap()
97 );
98
99 // Example 5: VQE Optimization (mock demonstration)
100 println!("\n5. VQE Optimization");
101 println!("-------------------");
102
103 let optimizer = VQEOptimizer::new(VQEOptimizerType::GradientDescent);
104 println!(
105 "Created optimizer with max iterations: {}",
106 optimizer.max_iterations
107 );
108 println!("Tolerance: {:.2e}", optimizer.tolerance);
109 println!("Learning rate: {}", optimizer.learning_rate);
110
111 // In a real implementation, this would actually optimize the parameters
112 let result = optimizer.optimize(&mut custom_vqe, &custom_obs)?;
113 println!("Optimization result:");
114 println!(" Ground state energy: {:.6}", result.ground_state_energy);
115 println!(" Converged: {}", result.converged);
116 println!(" Iterations: {}", result.iterations);
117 println!(" Gradient norm: {:.2e}", result.gradient_norm);
118
119 // Example 6: Different optimizer types
120 println!("\n6. Different Optimizer Types");
121 println!("----------------------------");
122
123 let optimizers = vec![
124 ("Gradient Descent", VQEOptimizerType::GradientDescent),
125 (
126 "Adam",
127 VQEOptimizerType::Adam {
128 beta1: 0.9,
129 beta2: 0.999,
130 },
131 ),
132 ("BFGS", VQEOptimizerType::BFGS),
133 ("Nelder-Mead", VQEOptimizerType::NelderMead),
134 (
135 "SPSA",
136 VQEOptimizerType::SPSA {
137 alpha: 0.602,
138 gamma: 0.101,
139 },
140 ),
141 ];
142
143 for (name, opt_type) in optimizers {
144 let opt = VQEOptimizer::new(opt_type);
145 println!(" {}: {:?}", name, opt.optimizer_type);
146 }
147
148 // Example 7: Real-space ansatz
149 println!("\n7. Real-Space Ansatz");
150 println!("--------------------");
151
152 let geometry = vec![
153 (0.0, 0.0, 0.0), // Site 0
154 (1.0, 0.0, 0.0), // Site 1
155 (0.0, 1.0, 0.0), // Site 2
156 (1.0, 1.0, 0.0), // Site 3
157 ];
158
159 let real_space_circuit = VQECircuit::<4>::new(VQEAnsatz::RealSpace { geometry })?;
160 println!(
161 "Real-space circuit with {} parameters",
162 real_space_circuit.num_parameters()
163 );
164 println!("Based on 2x2 square lattice geometry");
165
166 // Example 8: Molecular Hamiltonian
167 println!("\n8. Molecular Hamiltonian");
168 println!("------------------------");
169
170 // Example one-body and two-body integrals (simplified)
171 let one_body = vec![
172 (0, 0, -1.0), // h_00
173 (1, 1, -1.0), // h_11
174 (0, 1, -0.5), // h_01
175 ];
176
177 let two_body = vec![
178 (0, 1, 0, 1, 0.5), // (00|11)
179 (0, 0, 1, 1, 0.3), // (01|01)
180 ];
181
182 let molecular_ham = VQEObservable::molecular_hamiltonian(&one_body, &two_body);
183 println!(
184 "Molecular Hamiltonian with {} terms",
185 molecular_ham.terms.len()
186 );
187
188 println!("\n✅ VQE Demo completed successfully!");
189 println!("\nNote: This demo shows the VQE framework structure.");
190 println!("Real VQE optimization requires quantum simulation or hardware execution.");
191
192 Ok(())
193}
12fn main() -> Result<(), Box<dyn std::error::Error>> {
13 println!("🔄 Quantum-Classical Co-optimization Demo");
14 println!("=========================================\n");
15
16 // Example 1: Basic hybrid problem setup
17 println!("1. Setting up a Hybrid Optimization Problem");
18 println!("-------------------------------------------");
19
20 let mut problem = HybridOptimizationProblem::<4>::new();
21
22 // Set global parameters for the optimization
23 problem.set_global_parameters(vec![0.1, 0.2, 0.3, 0.4, 0.5, 0.6]);
24 println!("Set {} global parameters", problem.global_parameters.len());
25
26 // Create a quantum circuit component
27 let mut quantum_circuit = Circuit::<4>::new();
28 quantum_circuit.h(Qubit(0))?;
29 quantum_circuit.cnot(Qubit(0), Qubit(1))?;
30 quantum_circuit.ry(Qubit(2), 0.0)?; // Will be parameterized
31 quantum_circuit.cnot(Qubit(2), Qubit(3))?;
32
33 // Add quantum component to the problem
34 problem.add_quantum_component(
35 "quantum_processor".to_string(),
36 quantum_circuit,
37 vec![0, 1, 2], // Use parameters 0, 1, 2 from global parameter vector
38 )?;
39
40 println!(
41 "Added quantum circuit component with {} gates",
42 problem.quantum_circuits[0].circuit.num_gates()
43 );
44
45 // Example 2: Adding classical processing steps
46 println!("\n2. Adding Classical Processing Steps");
47 println!("-----------------------------------");
48
49 // Add a classical linear algebra step
50 problem.add_classical_step(
51 "matrix_operations".to_string(),
52 ClassicalStepType::LinearAlgebra(LinearAlgebraOp::MatrixMultiplication),
53 vec!["quantum_processor".to_string()],
54 vec!["processed_measurements".to_string()],
55 )?;
56
57 // Add a machine learning inference step
58 problem.add_classical_step(
59 "ml_inference".to_string(),
60 ClassicalStepType::MachineLearning(QCMLModelType::NeuralNetwork),
61 vec!["processed_measurements".to_string()],
62 vec!["ml_output".to_string()],
63 )?;
64
65 // Add a parameter update step
66 problem.add_classical_step(
67 "parameter_update".to_string(),
68 ClassicalStepType::ParameterUpdate(UpdateRule::AdamOptimizer),
69 vec!["ml_output".to_string()],
70 vec!["updated_parameters".to_string()],
71 )?;
72
73 println!(
74 "Added {} classical processing steps",
75 problem.classical_steps.len()
76 );
77
78 // Print details of each classical step
79 for (i, step) in problem.classical_steps.iter().enumerate() {
80 println!(" Step {}: {} ({:?})", i + 1, step.id, step.step_type);
81 }
82
83 // Example 3: Setting up data flow
84 println!("\n3. Setting up Data Flow");
85 println!("-----------------------");
86
87 // Connect quantum processor to matrix operations
88 problem.add_data_flow(
89 "quantum_processor".to_string(),
90 "matrix_operations".to_string(),
91 DataType::Measurements(vec![0.5, 0.3, 0.8, 0.1]),
92 )?;
93
94 // Connect matrix operations to ML inference
95 problem.add_data_flow(
96 "matrix_operations".to_string(),
97 "ml_inference".to_string(),
98 DataType::Matrix(vec![vec![1.0, 0.5], vec![0.3, 0.8]]),
99 )?;
100
101 // Connect ML inference to parameter update
102 problem.add_data_flow(
103 "ml_inference".to_string(),
104 "parameter_update".to_string(),
105 DataType::Scalar(0.75),
106 )?;
107
108 println!(
109 "Set up {} data flow connections",
110 problem.data_flow.edges.len()
111 );
112
113 // Print data flow details
114 for (i, (source, target, data_type)) in problem.data_flow.edges.iter().enumerate() {
115 println!(
116 " Flow {}: {} -> {} ({:?})",
117 i + 1,
118 source,
119 target,
120 data_type
121 );
122 }
123
124 // Example 4: Adding regularization
125 println!("\n4. Adding Regularization Terms");
126 println!("------------------------------");
127
128 // Add L2 regularization on parameters 0-2
129 problem.add_regularization(RegularizationType::L2, 0.01, vec![0, 1, 2])?;
130
131 // Add sparsity regularization on parameters 3-5
132 problem.add_regularization(RegularizationType::Sparsity, 0.005, vec![3, 4, 5])?;
133
134 println!(
135 "Added {} regularization terms",
136 problem.objective.regularization.len()
137 );
138
139 for (i, reg) in problem.objective.regularization.iter().enumerate() {
140 println!(
141 " Regularization {}: {:?} (strength: {:.3})",
142 i + 1,
143 reg.reg_type,
144 reg.strength
145 );
146 }
147
148 // Example 5: Validating the problem
149 println!("\n5. Problem Validation");
150 println!("---------------------");
151
152 match problem.validate() {
153 Ok(()) => println!("✅ Problem validation passed"),
154 Err(e) => println!("❌ Problem validation failed: {}", e),
155 }
156
157 println!("Total components: {}", problem.data_flow.nodes.len());
158 println!("Total connections: {}", problem.data_flow.edges.len());
159
160 // Example 6: Different optimization algorithms
161 println!("\n6. Optimization Algorithms");
162 println!("--------------------------");
163
164 let algorithms = vec![
165 (
166 "Coordinate Descent",
167 HybridOptimizationAlgorithm::CoordinateDescent,
168 ),
169 (
170 "Simultaneous Optimization",
171 HybridOptimizationAlgorithm::SimultaneousOptimization,
172 ),
173 (
174 "Hierarchical Optimization",
175 HybridOptimizationAlgorithm::HierarchicalOptimization,
176 ),
177 (
178 "Adaptive Optimization",
179 HybridOptimizationAlgorithm::AdaptiveOptimization,
180 ),
181 ];
182
183 for (name, algorithm) in algorithms {
184 let optimizer = HybridOptimizer::new(algorithm.clone());
185 println!(" {}: {:?}", name, optimizer.algorithm);
186 println!(" Max iterations: {}", optimizer.max_iterations);
187 println!(" Tolerance: {:.2e}", optimizer.tolerance);
188 println!(
189 " Initial learning rate: {}",
190 optimizer.learning_rate_schedule.initial_rate
191 );
192 }
193
194 // Example 7: Learning rate schedules
195 println!("\n7. Learning Rate Schedules");
196 println!("--------------------------");
197
198 let mut optimizer = HybridOptimizer::new(HybridOptimizationAlgorithm::SimultaneousOptimization);
199
200 // Set up different schedules
201 let schedules = vec![
202 ("Constant", ScheduleType::Constant),
203 ("Linear Decay", ScheduleType::LinearDecay),
204 ("Exponential Decay", ScheduleType::ExponentialDecay),
205 ("Step Decay", ScheduleType::StepDecay),
206 ("Cosine Annealing", ScheduleType::CosineAnnealing),
207 ];
208
209 for (name, schedule_type) in schedules {
210 optimizer.learning_rate_schedule.schedule_type = schedule_type.clone();
211 println!(" {}: {:?}", name, schedule_type);
212 }
213
214 // Example 8: Parallelization configuration
215 println!("\n8. Parallelization Configuration");
216 println!("--------------------------------");
217
218 optimizer.parallelization.quantum_parallelism = 4;
219 optimizer.parallelization.classical_parallelism = 8;
220 optimizer.parallelization.asynchronous = true;
221 optimizer.parallelization.load_balancing = LoadBalancingStrategy::WorkStealing;
222
223 println!(
224 "Quantum parallelism: {} circuits",
225 optimizer.parallelization.quantum_parallelism
226 );
227 println!(
228 "Classical parallelism: {} threads",
229 optimizer.parallelization.classical_parallelism
230 );
231 println!(
232 "Asynchronous execution: {}",
233 optimizer.parallelization.asynchronous
234 );
235 println!(
236 "Load balancing: {:?}",
237 optimizer.parallelization.load_balancing
238 );
239
240 // Example 9: Running optimization (mock)
241 println!("\n9. Running Optimization");
242 println!("-----------------------");
243
244 println!("Starting hybrid optimization...");
245 let result = optimizer.optimize(&mut problem)?;
246
247 println!("Optimization completed:");
248 println!(" Optimal value: {:.6}", result.optimal_value);
249 println!(" Converged: {}", result.converged);
250 println!(" Iterations: {}", result.iterations);
251 println!(" Final parameters: {:?}", result.optimal_parameters);
252
253 // Print some history information
254 if !result.history.objective_values.is_empty() {
255 println!(" Objective value history (first 5):");
256 for (i, &value) in result.history.objective_values.iter().take(5).enumerate() {
257 println!(" Iteration {}: {:.6}", i, value);
258 }
259 }
260
261 if !result.history.gradient_norms.is_empty() {
262 let final_gradient = result.history.gradient_norms.last().unwrap();
263 println!(" Final gradient norm: {:.2e}", final_gradient);
264 }
265
266 // Example 10: Specific hybrid algorithm patterns
267 println!("\n10. Common Hybrid Algorithm Patterns");
268 println!("------------------------------------");
269
270 // QAOA-like pattern
271 println!("QAOA-like pattern:");
272 println!(" 1. Prepare initial state (quantum)");
273 println!(" 2. Apply parameterized unitaries (quantum)");
274 println!(" 3. Measure expectation values (quantum)");
275 println!(" 4. Classical optimization step (classical)");
276 println!(" 5. Repeat until convergence");
277
278 // VQE with neural network pattern
279 println!("\nVQE with Neural Network pattern:");
280 println!(" 1. Prepare ansatz circuit (quantum)");
281 println!(" 2. Measure Pauli expectations (quantum)");
282 println!(" 3. Neural network post-processing (classical)");
283 println!(" 4. Gradient-based parameter update (classical)");
284 println!(" 5. Repeat until convergence");
285
286 // Quantum-enhanced ML pattern
287 println!("\nQuantum-enhanced ML pattern:");
288 println!(" 1. Classical feature encoding (classical)");
289 println!(" 2. Quantum feature mapping (quantum)");
290 println!(" 3. Quantum measurements (quantum)");
291 println!(" 4. Classical ML inference (classical)");
292 println!(" 5. End-to-end gradient updates (hybrid)");
293
294 // Example 11: Data types and flow
295 println!("\n11. Data Types in Hybrid Algorithms");
296 println!("-----------------------------------");
297
298 let data_types = vec![
299 (
300 "Quantum measurements",
301 "Raw measurement outcomes from quantum circuits",
302 ),
303 (
304 "Probability distributions",
305 "Estimated probability distributions from measurements",
306 ),
307 (
308 "Classical matrices",
309 "Processed data in matrix form for linear algebra",
310 ),
311 (
312 "Scalar values",
313 "Single numerical values like energies or costs",
314 ),
315 (
316 "Parameter vectors",
317 "Optimization parameters for both quantum and classical components",
318 ),
319 (
320 "Control signals",
321 "Boolean flags for adaptive algorithm control",
322 ),
323 ];
324
325 for (dtype, description) in data_types {
326 println!(" {}: {}", dtype, description);
327 }
328
329 println!("\n✅ Quantum-Classical Co-optimization Demo completed!");
330 println!("\nNote: This demo shows the framework structure for hybrid optimization.");
331 println!("Real co-optimization requires actual quantum and classical execution engines.");
332
333 Ok(())
334}
Sourcepub fn cx(
&mut self,
control: impl Into<QubitId>,
target: impl Into<QubitId>,
) -> QuantRS2Result<&mut Self>
pub fn cx( &mut self, control: impl Into<QubitId>, target: impl Into<QubitId>, ) -> QuantRS2Result<&mut Self>
Apply a CNOT gate (alias for cnot)
Examples found in repository?
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}
Sourcepub fn cy(
&mut self,
control: impl Into<QubitId>,
target: impl Into<QubitId>,
) -> QuantRS2Result<&mut Self>
pub fn cy( &mut self, control: impl Into<QubitId>, target: impl Into<QubitId>, ) -> QuantRS2Result<&mut Self>
Apply a CY gate (Controlled-Y)
Sourcepub fn cz(
&mut self,
control: impl Into<QubitId>,
target: impl Into<QubitId>,
) -> QuantRS2Result<&mut Self>
pub fn cz( &mut self, control: impl Into<QubitId>, target: impl Into<QubitId>, ) -> QuantRS2Result<&mut Self>
Apply a CZ gate (Controlled-Z)
Examples found in repository?
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}
Sourcepub fn ch(
&mut self,
control: impl Into<QubitId>,
target: impl Into<QubitId>,
) -> QuantRS2Result<&mut Self>
pub fn ch( &mut self, control: impl Into<QubitId>, target: impl Into<QubitId>, ) -> QuantRS2Result<&mut Self>
Apply a CH gate (Controlled-Hadamard)
Sourcepub fn cs(
&mut self,
control: impl Into<QubitId>,
target: impl Into<QubitId>,
) -> QuantRS2Result<&mut Self>
pub fn cs( &mut self, control: impl Into<QubitId>, target: impl Into<QubitId>, ) -> QuantRS2Result<&mut Self>
Apply a CS gate (Controlled-Phase/S)
Sourcepub fn crx(
&mut self,
control: impl Into<QubitId>,
target: impl Into<QubitId>,
theta: f64,
) -> QuantRS2Result<&mut Self>
pub fn crx( &mut self, control: impl Into<QubitId>, target: impl Into<QubitId>, theta: f64, ) -> QuantRS2Result<&mut Self>
Apply a controlled rotation around X-axis (CRX)
Sourcepub fn cry(
&mut self,
control: impl Into<QubitId>,
target: impl Into<QubitId>,
theta: f64,
) -> QuantRS2Result<&mut Self>
pub fn cry( &mut self, control: impl Into<QubitId>, target: impl Into<QubitId>, theta: f64, ) -> QuantRS2Result<&mut Self>
Apply a controlled rotation around Y-axis (CRY)
Sourcepub fn crz(
&mut self,
control: impl Into<QubitId>,
target: impl Into<QubitId>,
theta: f64,
) -> QuantRS2Result<&mut Self>
pub fn crz( &mut self, control: impl Into<QubitId>, target: impl Into<QubitId>, theta: f64, ) -> QuantRS2Result<&mut Self>
Apply a controlled rotation around Z-axis (CRZ)
Sourcepub fn cp(
&mut self,
control: impl Into<QubitId>,
target: impl Into<QubitId>,
lambda: f64,
) -> QuantRS2Result<&mut Self>
pub fn cp( &mut self, control: impl Into<QubitId>, target: impl Into<QubitId>, lambda: f64, ) -> QuantRS2Result<&mut Self>
Apply a controlled phase gate
Sourcepub fn swap(
&mut self,
qubit1: impl Into<QubitId>,
qubit2: impl Into<QubitId>,
) -> QuantRS2Result<&mut Self>
pub fn swap( &mut self, qubit1: impl Into<QubitId>, qubit2: impl Into<QubitId>, ) -> QuantRS2Result<&mut Self>
Apply a SWAP gate
Sourcepub fn toffoli(
&mut self,
control1: impl Into<QubitId>,
control2: impl Into<QubitId>,
target: impl Into<QubitId>,
) -> QuantRS2Result<&mut Self>
pub fn toffoli( &mut self, control1: impl Into<QubitId>, control2: impl Into<QubitId>, target: impl Into<QubitId>, ) -> QuantRS2Result<&mut Self>
Apply a Toffoli (CCNOT) gate
Examples found in repository?
33fn create_sample_circuit() -> Circuit<4> {
34 // Create a circuit that has optimization opportunities
35 let mut circuit = Circuit::<4>::new();
36
37 // Add some gates with optimization opportunities
38 // Pattern 1: Redundant gates (H-H = I, X-X = I)
39 let _ = circuit.h(0);
40 let _ = circuit.h(0);
41
42 // Pattern 2: Commutable gates
43 let _ = circuit.x(1);
44 let _ = circuit.z(0);
45 let _ = circuit.cnot(0, 1);
46
47 // Pattern 3: Mergeable rotations
48 let _ = circuit.rz(2, std::f64::consts::PI / 4.0);
49 let _ = circuit.rz(2, std::f64::consts::PI / 4.0);
50
51 // Pattern 4: Known patterns (H-X-H = Z)
52 let _ = circuit.h(3);
53 let _ = circuit.x(3);
54 let _ = circuit.h(3);
55
56 // Pattern 5: Decomposable gates
57 let _ = circuit.toffoli(0, 1, 2);
58
59 circuit
60}
Sourcepub fn cswap(
&mut self,
control: impl Into<QubitId>,
target1: impl Into<QubitId>,
target2: impl Into<QubitId>,
) -> QuantRS2Result<&mut Self>
pub fn cswap( &mut self, control: impl Into<QubitId>, target1: impl Into<QubitId>, target2: impl Into<QubitId>, ) -> QuantRS2Result<&mut Self>
Apply a Fredkin (CSWAP) gate
Sourcepub fn measure(
&mut self,
qubit: impl Into<QubitId>,
) -> QuantRS2Result<&mut Self>
pub fn measure( &mut self, qubit: impl Into<QubitId>, ) -> QuantRS2Result<&mut Self>
Measure a qubit (currently adds a placeholder measure gate)
Note: This is currently a placeholder implementation for QASM export compatibility. For actual quantum measurements, use the measurement module functionality.
Examples found in repository?
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}
Sourcepub fn reset(&mut self, _qubit: impl Into<QubitId>) -> QuantRS2Result<&mut Self>
pub fn reset(&mut self, _qubit: impl Into<QubitId>) -> QuantRS2Result<&mut Self>
Reset a qubit to |0⟩ state
Note: This operation is not yet fully implemented. Reset operations are complex and require special handling in quantum circuits.
Sourcepub fn barrier(&mut self, qubits: &[QubitId]) -> QuantRS2Result<&mut Self>
pub fn barrier(&mut self, qubits: &[QubitId]) -> QuantRS2Result<&mut Self>
Add a barrier to prevent optimization across this point
Barriers are used to prevent gate optimization algorithms from reordering gates across specific points in the circuit. This is useful for maintaining timing constraints or preserving specific circuit structure.
Sourcepub fn run<S: Simulator<N>>(&self, simulator: S) -> QuantRS2Result<Register<N>>
pub fn run<S: Simulator<N>>(&self, simulator: S) -> QuantRS2Result<Register<N>>
Run the circuit on a simulator
Sourcepub fn decompose(&self) -> QuantRS2Result<Self>
pub fn decompose(&self) -> QuantRS2Result<Self>
Decompose the circuit into a sequence of standard gates
This method will return a new circuit with complex gates decomposed into sequences of simpler gates.
Sourcepub fn build(self) -> Self
pub fn build(self) -> Self
Build the circuit (for compatibility - returns self)
Examples found in repository?
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}
Sourcepub fn optimize(&self) -> QuantRS2Result<Self>
pub fn optimize(&self) -> QuantRS2Result<Self>
Optimize the circuit by combining or removing gates
This method will return a new circuit with simplified gates by removing unnecessary gates or combining adjacent gates.
Sourcepub fn create_composite(
&self,
start_idx: usize,
end_idx: usize,
name: &str,
) -> QuantRS2Result<CompositeGate>
pub fn create_composite( &self, start_idx: usize, end_idx: usize, name: &str, ) -> QuantRS2Result<CompositeGate>
Create a composite gate from a subsequence of this circuit
This method allows creating a custom gate that combines several other gates, which can be applied as a single unit to a circuit.
Sourcepub fn add_composite(
&mut self,
composite: &CompositeGate,
) -> QuantRS2Result<&mut Self>
pub fn add_composite( &mut self, composite: &CompositeGate, ) -> QuantRS2Result<&mut Self>
Add all gates from a composite gate to this circuit
Sourcepub fn measure_all(&mut self) -> QuantRS2Result<&mut Self>
pub fn measure_all(&mut self) -> QuantRS2Result<&mut Self>
Measure all qubits in the circuit
Sourcepub fn with_classical_control(self) -> ClassicalCircuit<N>
pub fn with_classical_control(self) -> ClassicalCircuit<N>
Convert this circuit to a ClassicalCircuit with classical control support
Examples found in repository?
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}
Source§impl<const N: usize> Circuit<N>
Extension trait for circuit slicing
impl<const N: usize> Circuit<N>
Extension trait for circuit slicing
Sourcepub fn slice(&self, strategy: SlicingStrategy) -> SlicingResult
pub fn slice(&self, strategy: SlicingStrategy) -> SlicingResult
Slice this circuit using the given strategy
Source§impl<const N: usize> Circuit<N>
Extension methods for circuits
impl<const N: usize> Circuit<N>
Extension methods for circuits
Sourcepub fn topological_analysis(&self) -> TopologicalAnalysis
pub fn topological_analysis(&self) -> TopologicalAnalysis
Perform topological analysis
Sourcepub fn topological_sort(&self, strategy: TopologicalStrategy) -> Vec<usize>
pub fn topological_sort(&self, strategy: TopologicalStrategy) -> Vec<usize>
Get topological order with specific strategy
Trait Implementations§
Auto Trait Implementations§
impl<const N: usize> Freeze for Circuit<N>
impl<const N: usize> !RefUnwindSafe for Circuit<N>
impl<const N: usize> Send for Circuit<N>
impl<const N: usize> Sync for Circuit<N>
impl<const N: usize> Unpin for Circuit<N>
impl<const N: usize> !UnwindSafe for Circuit<N>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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 moreSource§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self
from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self
is actually part of its subset T
(and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset
but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self
to the equivalent element of its superset.