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::autodiff::optimizers::Adam;
15use 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 Few-Shot Learning Demo ===\n");
22
23 println!("1. Generating synthetic dataset for 5-way classification...");
25 let num_samples_per_class = 20;
26 let num_classes = 5;
27 let num_features = 4;
28 let total_samples = num_samples_per_class * num_classes;
29
30 let mut data = Array2::zeros((total_samples, num_features));
32 let mut labels = Array1::zeros(total_samples);
33
34 for class_id in 0..num_classes {
35 for sample_idx in 0..num_samples_per_class {
36 let idx = class_id * num_samples_per_class + sample_idx;
37
38 for feat in 0..num_features {
40 data[[idx, feat]] = 0.1f64.mul_add(
41 2.0f64.mul_add(thread_rng().gen::<f64>(), -1.0),
42 (sample_idx as f64)
43 .mul_add(0.1, (class_id as f64).mul_add(0.5, feat as f64 * 0.3))
44 .sin(),
45 );
46 }
47 labels[idx] = class_id;
48 }
49 }
50
51 println!(
52 " Dataset created: {total_samples} samples, {num_features} features, {num_classes} classes"
53 );
54
55 println!("\n2. Creating quantum neural network...");
57 let layers = vec![
58 QNNLayerType::EncodingLayer { num_features },
59 QNNLayerType::VariationalLayer { num_params: 8 },
60 QNNLayerType::EntanglementLayer {
61 connectivity: "circular".to_string(),
62 },
63 QNNLayerType::VariationalLayer { num_params: 8 },
64 QNNLayerType::MeasurementLayer {
65 measurement_basis: "computational".to_string(),
66 },
67 ];
68
69 let qnn = QuantumNeuralNetwork::new(layers, 4, num_features, num_classes)?;
70 println!(" Quantum model created with {} qubits", qnn.num_qubits);
71
72 println!("\n3. Testing few-shot learning methods:");
74
75 println!("\n a) Prototypical Networks (5-way 3-shot):");
77 test_prototypical_networks(&data, &labels, qnn.clone())?;
78
79 println!("\n b) Model-Agnostic Meta-Learning (MAML):");
81 test_maml(&data, &labels, qnn.clone())?;
82
83 println!("\n4. Performance comparison across different K-shot values:");
85 compare_shot_performance(&data, &labels, qnn)?;
86
87 println!("\n=== Few-Shot Learning Demo Complete ===");
88
89 Ok(())
90}
91
92fn test_prototypical_networks(
94 data: &Array2<f64>,
95 labels: &Array1<usize>,
96 qnn: QuantumNeuralNetwork,
97) -> Result<()> {
98 let mut learner = FewShotLearner::new(FewShotMethod::PrototypicalNetworks, qnn);
99
100 let num_episodes = 10;
102 let mut episodes = Vec::new();
103
104 for _ in 0..num_episodes {
105 let episode = FewShotLearner::generate_episode(
106 data, labels, 5, 3, 5, )?;
110 episodes.push(episode);
111 }
112
113 let mut optimizer = Adam::new(0.01);
115 let accuracies = learner.train(&episodes, &mut optimizer, 20)?;
116
117 println!(" Training completed:");
119 println!(" - Initial accuracy: {:.2}%", accuracies[0] * 100.0);
120 println!(
121 " - Final accuracy: {:.2}%",
122 accuracies.last().unwrap() * 100.0
123 );
124 println!(
125 " - Improvement: {:.2}%",
126 (accuracies.last().unwrap() - accuracies[0]) * 100.0
127 );
128
129 Ok(())
130}
131
132fn test_maml(data: &Array2<f64>, labels: &Array1<usize>, qnn: QuantumNeuralNetwork) -> Result<()> {
134 let mut learner = FewShotLearner::new(
135 FewShotMethod::MAML {
136 inner_steps: 5,
137 inner_lr: 0.01,
138 },
139 qnn,
140 );
141
142 let num_tasks = 20;
144 let mut tasks = Vec::new();
145
146 for _ in 0..num_tasks {
147 let task = FewShotLearner::generate_episode(
148 data, labels, 3, 5, 5, )?;
152 tasks.push(task);
153 }
154
155 let mut meta_optimizer = Adam::new(0.001);
157 let losses = learner.train(&tasks, &mut meta_optimizer, 10)?;
158
159 println!(" Meta-training completed:");
160 println!(" - Initial loss: {:.4}", losses[0]);
161 println!(" - Final loss: {:.4}", losses.last().unwrap());
162 println!(
163 " - Convergence rate: {:.2}%",
164 (1.0 - losses.last().unwrap() / losses[0]) * 100.0
165 );
166
167 Ok(())
168}
169
170fn compare_shot_performance(
172 data: &Array2<f64>,
173 labels: &Array1<usize>,
174 qnn: QuantumNeuralNetwork,
175) -> Result<()> {
176 let k_values = vec![1, 3, 5, 10];
177
178 for k in k_values {
179 println!("\n Testing {k}-shot learning:");
180
181 let mut learner = FewShotLearner::new(FewShotMethod::PrototypicalNetworks, qnn.clone());
182
183 let mut episodes = Vec::new();
185 for _ in 0..5 {
186 let episode = FewShotLearner::generate_episode(
187 data, labels, 3, k, 5, )?;
191 episodes.push(episode);
192 }
193
194 let mut optimizer = Adam::new(0.01);
196 let accuracies = learner.train(&episodes, &mut optimizer, 10)?;
197
198 println!(
199 " Final accuracy: {:.2}%",
200 accuracies.last().unwrap() * 100.0
201 );
202 }
203
204 Ok(())
205}
206
207fn demonstrate_episode_structure() -> Result<()> {
209 println!("\n5. Episode Structure Demonstration:");
210
211 let support_set = vec![
213 (Array1::from_vec(vec![0.1, 0.2, 0.3, 0.4]), 0),
215 (Array1::from_vec(vec![0.15, 0.25, 0.35, 0.45]), 0),
216 (Array1::from_vec(vec![0.8, 0.7, 0.6, 0.5]), 1),
218 (Array1::from_vec(vec![0.85, 0.75, 0.65, 0.55]), 1),
219 ];
220
221 let query_set = vec![
222 (Array1::from_vec(vec![0.12, 0.22, 0.32, 0.42]), 0),
223 (Array1::from_vec(vec![0.82, 0.72, 0.62, 0.52]), 1),
224 ];
225
226 let episode = Episode {
227 support_set,
228 query_set,
229 num_classes: 2,
230 k_shot: 2,
231 };
232
233 println!(" 2-way 2-shot episode created");
234 println!(" - Support set size: {}", episode.support_set.len());
235 println!(" - Query set size: {}", episode.query_set.len());
236
237 Ok(())
238}