1#![allow(
2 clippy::pedantic,
3 clippy::unnecessary_wraps,
4 clippy::needless_range_loop,
5 clippy::useless_vec,
6 clippy::needless_collect,
7 clippy::too_many_arguments
8)]
9use quantrs2_ml::prelude::*;
16use quantrs2_ml::qnn::QNNLayerType;
17use scirs2_core::ndarray::{Array1, Array2};
18use scirs2_core::random::prelude::*;
19
20fn main() -> Result<()> {
21 println!("=== Quantum Neural Architecture Search Demo ===\n");
22
23 println!("1. Evolutionary Algorithm Search...");
25 evolutionary_search_demo()?;
26
27 println!("\n2. Random Search Baseline...");
29 random_search_demo()?;
30
31 println!("\n3. Reinforcement Learning Search...");
33 rl_search_demo()?;
34
35 println!("\n4. Bayesian Optimization Search...");
37 bayesian_search_demo()?;
38
39 println!("\n5. DARTS (Differentiable Architecture Search)...");
41 darts_demo()?;
42
43 println!("\n6. Multi-Objective Optimization...");
45 multi_objective_demo()?;
46
47 println!("\n7. Architecture Analysis...");
49 architecture_analysis_demo()?;
50
51 println!("\n=== Quantum NAS Demo Complete ===");
52
53 Ok(())
54}
55
56fn evolutionary_search_demo() -> Result<()> {
58 let search_space = create_default_search_space();
60
61 let strategy = SearchStrategy::Evolutionary {
63 population_size: 20,
64 mutation_rate: 0.2,
65 crossover_rate: 0.7,
66 elitism_ratio: 0.1,
67 };
68
69 let mut nas = QuantumNAS::new(strategy, search_space);
70
71 println!(" Created evolutionary NAS:");
72 println!(" - Population size: 20");
73 println!(" - Mutation rate: 0.2");
74 println!(" - Crossover rate: 0.7");
75 println!(" - Elitism ratio: 0.1");
76
77 let eval_data = Array2::from_shape_fn((100, 4), |(i, j)| (i as f64 + j as f64) / 50.0);
79 let eval_labels = Array1::from_shape_fn(100, |i| i % 2);
80 nas.set_evaluation_data(eval_data, eval_labels);
81
82 println!("\n Running evolutionary search for 10 generations...");
84 let best_architectures = nas.search(10)?;
85
86 println!(" Search complete!");
87 println!(
88 " - Best architectures found: {}",
89 best_architectures.len()
90 );
91
92 if let Some(best) = best_architectures.first() {
93 println!(" - Best architecture: {best}");
94 println!(" - Circuit depth: {}", best.metrics.circuit_depth);
95 println!(" - Parameter count: {}", best.metrics.parameter_count);
96
97 if let Some(expressivity) = best.properties.expressivity {
98 println!(" - Expressivity: {expressivity:.3}");
99 }
100 }
101
102 let summary = nas.get_search_summary();
104 println!(
105 " - Total architectures evaluated: {}",
106 summary.total_architectures_evaluated
107 );
108 println!(" - Pareto front size: {}", summary.pareto_front_size);
109
110 Ok(())
111}
112
113fn random_search_demo() -> Result<()> {
115 let search_space = create_default_search_space();
116 let strategy = SearchStrategy::Random { num_samples: 50 };
117
118 let mut nas = QuantumNAS::new(strategy, search_space);
119
120 println!(" Created random search NAS:");
121 println!(" - Number of samples: 50");
122
123 let eval_data = Array2::from_shape_fn((80, 4), |(i, j)| {
125 0.5f64.mul_add((i as f64).sin(), 0.3 * (j as f64).cos())
126 });
127 let eval_labels = Array1::from_shape_fn(80, |i| usize::from(i % 3 != 0));
128 nas.set_evaluation_data(eval_data, eval_labels);
129
130 println!("\n Running random search...");
131 let best_architectures = nas.search(50)?;
132
133 println!(" Random search complete!");
134 if let Some(best) = best_architectures.first() {
135 println!(" - Best random architecture: {best}");
136 if let Some(accuracy) = best.metrics.accuracy {
137 println!(" - Accuracy: {accuracy:.3}");
138 }
139 }
140
141 Ok(())
142}
143
144fn rl_search_demo() -> Result<()> {
146 let search_space = create_custom_search_space();
147
148 let strategy = SearchStrategy::ReinforcementLearning {
149 agent_type: RLAgentType::PolicyGradient,
150 exploration_rate: 0.3,
151 learning_rate: 0.01,
152 };
153
154 let mut nas = QuantumNAS::new(strategy, search_space);
155
156 println!(" Created RL-based NAS:");
157 println!(" - Agent type: Policy Gradient");
158 println!(" - Exploration rate: 0.3");
159 println!(" - Learning rate: 0.01");
160
161 println!("\n Running RL search for 100 episodes...");
162 let best_architectures = nas.search(100)?;
163
164 println!(" RL search complete!");
165 println!(" - Architectures found: {}", best_architectures.len());
166
167 if let Some(best) = best_architectures.first() {
168 println!(" - Best RL architecture: {best}");
169 if let Some(entanglement) = best.properties.entanglement_capability {
170 println!(" - Entanglement capability: {entanglement:.3}");
171 }
172 }
173
174 Ok(())
175}
176
177fn bayesian_search_demo() -> Result<()> {
179 let search_space = create_default_search_space();
180
181 let strategy = SearchStrategy::BayesianOptimization {
182 acquisition_function: AcquisitionFunction::ExpectedImprovement,
183 num_initial_points: 10,
184 };
185
186 let mut nas = QuantumNAS::new(strategy, search_space);
187
188 println!(" Created Bayesian optimization NAS:");
189 println!(" - Acquisition function: Expected Improvement");
190 println!(" - Initial random points: 10");
191
192 let eval_data = generate_quantum_data(60, 4);
194 let eval_labels = Array1::from_shape_fn(60, |i| i % 3);
195 nas.set_evaluation_data(eval_data, eval_labels);
196
197 println!("\n Running Bayesian optimization for 30 iterations...");
198 let best_architectures = nas.search(30)?;
199
200 println!(" Bayesian optimization complete!");
201 if let Some(best) = best_architectures.first() {
202 println!(" - Best Bayesian architecture: {best}");
203 if let Some(hardware_eff) = best.metrics.hardware_efficiency {
204 println!(" - Hardware efficiency: {hardware_eff:.3}");
205 }
206 }
207
208 Ok(())
209}
210
211fn darts_demo() -> Result<()> {
213 let search_space = create_darts_search_space();
214
215 let strategy = SearchStrategy::DARTS {
216 learning_rate: 0.01,
217 weight_decay: 1e-4,
218 };
219
220 let mut nas = QuantumNAS::new(strategy, search_space);
221
222 println!(" Created DARTS NAS:");
223 println!(" - Learning rate: 0.01");
224 println!(" - Weight decay: 1e-4");
225 println!(" - Differentiable architecture search");
226
227 println!("\n Running DARTS for 200 epochs...");
228 let best_architectures = nas.search(200)?;
229
230 println!(" DARTS search complete!");
231 if let Some(best) = best_architectures.first() {
232 println!(" - DARTS architecture: {best}");
233 println!(" - Learned through gradient-based optimization");
234
235 if let Some(gradient_var) = best.properties.gradient_variance {
236 println!(" - Gradient variance: {gradient_var:.3}");
237 }
238 }
239
240 Ok(())
241}
242
243fn multi_objective_demo() -> Result<()> {
245 let search_space = create_default_search_space();
246
247 let strategy = SearchStrategy::Evolutionary {
248 population_size: 30,
249 mutation_rate: 0.15,
250 crossover_rate: 0.8,
251 elitism_ratio: 0.2,
252 };
253
254 let mut nas = QuantumNAS::new(strategy, search_space);
255
256 println!(" Multi-objective optimization:");
257 println!(" - Optimizing accuracy vs. complexity");
258 println!(" - Finding Pareto-optimal architectures");
259
260 nas.search(15)?;
262
263 let pareto_front = nas.get_pareto_front();
265 println!(" Pareto front analysis:");
266 println!(" - Pareto-optimal architectures: {}", pareto_front.len());
267
268 for (i, arch) in pareto_front.iter().take(3).enumerate() {
269 println!(
270 " Architecture {}: {} params, {:.3} accuracy",
271 i + 1,
272 arch.metrics.parameter_count,
273 arch.metrics.accuracy.unwrap_or(0.0)
274 );
275 }
276
277 Ok(())
278}
279
280fn architecture_analysis_demo() -> Result<()> {
282 println!(" Analyzing quantum circuit architectures...");
283
284 let architectures = create_sample_architectures();
286
287 println!("\n Architecture comparison:");
288 for (i, arch) in architectures.iter().enumerate() {
289 println!(" Architecture {}:", i + 1);
290 println!(" - Layers: {}", arch.layers.len());
291 println!(" - Qubits: {}", arch.num_qubits);
292 println!(" - Circuit depth: {}", arch.metrics.circuit_depth);
293
294 if let Some(expressivity) = arch.properties.expressivity {
295 println!(" - Expressivity: {expressivity:.3}");
296 }
297
298 if let Some(entanglement) = arch.properties.entanglement_capability {
299 println!(" - Entanglement: {entanglement:.3}");
300 }
301
302 if let Some(barren_plateau) = arch.properties.barren_plateau_score {
303 println!(" - Barren plateau risk: {barren_plateau:.3}");
304 }
305
306 println!();
307 }
308
309 println!(" Performance trade-offs:");
311 println!(" - Deeper circuits: higher expressivity, more barren plateaus");
312 println!(" - More entanglement: better feature mixing, higher noise sensitivity");
313 println!(" - More parameters: greater capacity, overfitting risk");
314
315 Ok(())
316}
317
318fn generate_quantum_data(samples: usize, features: usize) -> Array2<f64> {
320 Array2::from_shape_fn((samples, features), |(i, j)| {
321 let phase = (i as f64).mul_add(0.1, j as f64 * 0.2).sin();
322 let amplitude = (i as f64 / samples as f64).exp() * 0.5;
323 amplitude * phase + 0.1 * fastrand::f64()
324 })
325}
326
327fn create_custom_search_space() -> SearchSpace {
329 SearchSpace {
330 layer_types: vec![
331 QNNLayerType::VariationalLayer { num_params: 4 },
332 QNNLayerType::VariationalLayer { num_params: 8 },
333 QNNLayerType::EntanglementLayer {
334 connectivity: "circular".to_string(),
335 },
336 QNNLayerType::EntanglementLayer {
337 connectivity: "linear".to_string(),
338 },
339 ],
340 depth_range: (1, 5),
341 qubit_constraints: QubitConstraints {
342 min_qubits: 3,
343 max_qubits: 6,
344 topology: Some(QuantumTopology::Ring),
345 },
346 param_ranges: vec![("variational_params".to_string(), (3, 12))]
347 .into_iter()
348 .collect(),
349 connectivity_patterns: vec!["linear".to_string(), "circular".to_string()],
350 measurement_bases: vec!["computational".to_string(), "Pauli-Z".to_string()],
351 }
352}
353
354fn create_darts_search_space() -> SearchSpace {
356 SearchSpace {
357 layer_types: vec![
358 QNNLayerType::VariationalLayer { num_params: 6 },
359 QNNLayerType::VariationalLayer { num_params: 9 },
360 QNNLayerType::EntanglementLayer {
361 connectivity: "full".to_string(),
362 },
363 ],
364 depth_range: (3, 6),
365 qubit_constraints: QubitConstraints {
366 min_qubits: 4,
367 max_qubits: 4, topology: Some(QuantumTopology::Complete),
369 },
370 param_ranges: vec![("variational_params".to_string(), (6, 9))]
371 .into_iter()
372 .collect(),
373 connectivity_patterns: vec!["full".to_string()],
374 measurement_bases: vec!["computational".to_string()],
375 }
376}
377
378fn create_sample_architectures() -> Vec<ArchitectureCandidate> {
380 vec![
381 ArchitectureCandidate {
383 id: "simple".to_string(),
384 layers: vec![
385 QNNLayerType::EncodingLayer { num_features: 4 },
386 QNNLayerType::VariationalLayer { num_params: 6 },
387 QNNLayerType::MeasurementLayer {
388 measurement_basis: "computational".to_string(),
389 },
390 ],
391 num_qubits: 3,
392 metrics: ArchitectureMetrics {
393 accuracy: Some(0.65),
394 loss: Some(0.4),
395 circuit_depth: 3,
396 parameter_count: 6,
397 training_time: Some(10.0),
398 memory_usage: Some(512),
399 hardware_efficiency: Some(0.8),
400 },
401 properties: ArchitectureProperties {
402 expressivity: Some(0.3),
403 entanglement_capability: Some(0.2),
404 gradient_variance: Some(0.1),
405 barren_plateau_score: Some(0.2),
406 noise_resilience: Some(0.7),
407 },
408 },
409 ArchitectureCandidate {
411 id: "complex".to_string(),
412 layers: vec![
413 QNNLayerType::EncodingLayer { num_features: 6 },
414 QNNLayerType::VariationalLayer { num_params: 12 },
415 QNNLayerType::EntanglementLayer {
416 connectivity: "full".to_string(),
417 },
418 QNNLayerType::VariationalLayer { num_params: 12 },
419 QNNLayerType::EntanglementLayer {
420 connectivity: "circular".to_string(),
421 },
422 QNNLayerType::MeasurementLayer {
423 measurement_basis: "Pauli-Z".to_string(),
424 },
425 ],
426 num_qubits: 6,
427 metrics: ArchitectureMetrics {
428 accuracy: Some(0.85),
429 loss: Some(0.2),
430 circuit_depth: 8,
431 parameter_count: 24,
432 training_time: Some(45.0),
433 memory_usage: Some(2048),
434 hardware_efficiency: Some(0.4),
435 },
436 properties: ArchitectureProperties {
437 expressivity: Some(0.8),
438 entanglement_capability: Some(0.9),
439 gradient_variance: Some(0.3),
440 barren_plateau_score: Some(0.7),
441 noise_resilience: Some(0.3),
442 },
443 },
444 ArchitectureCandidate {
446 id: "balanced".to_string(),
447 layers: vec![
448 QNNLayerType::EncodingLayer { num_features: 4 },
449 QNNLayerType::VariationalLayer { num_params: 8 },
450 QNNLayerType::EntanglementLayer {
451 connectivity: "circular".to_string(),
452 },
453 QNNLayerType::VariationalLayer { num_params: 8 },
454 QNNLayerType::MeasurementLayer {
455 measurement_basis: "computational".to_string(),
456 },
457 ],
458 num_qubits: 4,
459 metrics: ArchitectureMetrics {
460 accuracy: Some(0.78),
461 loss: Some(0.28),
462 circuit_depth: 5,
463 parameter_count: 16,
464 training_time: Some(25.0),
465 memory_usage: Some(1024),
466 hardware_efficiency: Some(0.65),
467 },
468 properties: ArchitectureProperties {
469 expressivity: Some(0.6),
470 entanglement_capability: Some(0.5),
471 gradient_variance: Some(0.15),
472 barren_plateau_score: Some(0.4),
473 noise_resilience: Some(0.6),
474 },
475 },
476 ]
477}