pub fn amplitude_encode(data: &Array1<f64>) -> Result<Array1<Complex64>>Expand description
Amplitude encoding: encode classical data into quantum amplitudes
Examples found in repository?
examples/amplitude_encoding.rs (line 31)
23fn main() -> Result<()> {
24 println!("=== Amplitude Encoding: Classical Data → Quantum State ===\n");
25
26 // ---- Example 1: Simple 4-dimensional vector → 2 qubits ----
27 println!("--- Example 1: 4D vector (2 qubits) ---");
28 let v1 = array![1.0f64, 2.0, 3.0, 4.0];
29 let norm_v1: f64 = v1.iter().map(|x| x * x).sum::<f64>().sqrt();
30
31 let encoded1 = amplitude_encode(&v1)?;
32 let norm_enc1: f64 = encoded1.iter().map(|c| c.norm_sqr()).sum::<f64>().sqrt();
33
34 println!("Input vector : {:?}", v1.as_slice().expect("slice"));
35 println!("Input norm : {norm_v1:.6}");
36 println!("Encoded state:");
37 for (i, &) in encoded1.iter().enumerate() {
38 println!(
39 " |{i:02b}⟩ : amplitude = {:+.4}{:+.4}i (prob = {:.6})",
40 amp.re,
41 amp.im,
42 amp.norm_sqr()
43 );
44 }
45 println!("Encoded norm : {norm_enc1:.10} (should be 1.0)");
46
47 assert!(
48 (norm_enc1 - 1.0).abs() < 1e-10,
49 "Encoded state must be normalised, got norm={norm_enc1}"
50 );
51
52 // ---- Example 2: 8-dimensional image patch → 3 qubits ----
53 println!("\n--- Example 2: 8D image patch (3 qubits) ---");
54 // Simulating an 8-pixel grayscale image patch
55 let image_patch = array![0.1f64, 0.5, 0.9, 0.3, 0.7, 0.2, 0.8, 0.4];
56 let encoded2 = amplitude_encode(&image_patch)?;
57 let norm_enc2: f64 = encoded2.iter().map(|c| c.norm_sqr()).sum::<f64>().sqrt();
58
59 println!(
60 "Image patch (8 pixels): {:?}",
61 image_patch.as_slice().expect("slice")
62 );
63 println!("Quantum state norms² :");
64 for (i, &) in encoded2.iter().enumerate() {
65 let bar = "#".repeat((amp.norm_sqr() * 20.0).round() as usize);
66 println!(" |{i:03b}⟩ : {:.4} {bar}", amp.norm_sqr());
67 }
68 println!("Norm check : {norm_enc2:.10} (should be 1.0)");
69
70 assert!((norm_enc2 - 1.0).abs() < 1e-10, "Norm must be 1.0");
71
72 // ---- Example 3: Quantum inner product (dot product kernel) ----
73 // |⟨ψ_a|ψ_b⟩|² = (a·b)² / (‖a‖² ‖b‖²) — quantum kernel
74 println!("\n--- Example 3: Quantum Inner Product ---");
75
76 let a = array![1.0f64, 0.0, 0.0, 0.0]; // basis vector e1
77 let b = array![1.0f64, 0.0, 0.0, 0.0]; // identical → fidelity = 1
78 let c = array![0.0f64, 1.0, 0.0, 0.0]; // orthogonal → fidelity = 0
79 let d = array![1.0f64, 1.0, 0.0, 0.0]; // 45° angle → fidelity = 0.5
80
81 let enc_a = amplitude_encode(&a)?;
82 let enc_b = amplitude_encode(&b)?;
83 let enc_c = amplitude_encode(&c)?;
84 let enc_d = amplitude_encode(&d)?;
85
86 let fidelity_ab = quantum_fidelity(&enc_a, &enc_b);
87 let fidelity_ac = quantum_fidelity(&enc_a, &enc_c);
88 let fidelity_ad = quantum_fidelity(&enc_a, &enc_d);
89
90 println!(" ⟨e1|e1⟩² = {fidelity_ab:.6} (expected 1.0 — identical)");
91 println!(" ⟨e1|e2⟩² = {fidelity_ac:.6} (expected 0.0 — orthogonal)");
92 println!(" ⟨e1|d ⟩² = {fidelity_ad:.6} (expected 0.5 — 45°)");
93
94 assert!(
95 (fidelity_ab - 1.0).abs() < 1e-10,
96 "Identical vectors: fidelity=1"
97 );
98 assert!(fidelity_ac < 1e-10, "Orthogonal vectors: fidelity=0");
99 assert!((fidelity_ad - 0.5).abs() < 0.01, "45° angle: fidelity≈0.5");
100
101 // ---- Example 4: Zero vector error handling ----
102 println!("\n--- Example 4: Error handling (zero vector) ---");
103 let zero = array![0.0f64, 0.0, 0.0, 0.0];
104 match amplitude_encode(&zero) {
105 Err(e) => println!(" Zero vector rejected: {e} ✓"),
106 Ok(_) => panic!("Should have rejected zero vector"),
107 }
108
109 // ---- Summary ----
110 println!("\n=== Summary ===");
111 println!(" d=4 → 2 qubits (log₂(4) = 2)");
112 println!(" d=8 → 3 qubits (log₂(8) = 3)");
113 println!(" d=2^n data encoded in n qubits — exponential compression");
114 println!(" Quantum inner product computable in O(1) measurement shots");
115
116 println!("\nAll checks passed — OK");
117
118 Ok(())
119}