QMem/lib.rs
1//! # Quantum Memory Simulator
2//!
3//! A simple library for simulating quantum memory operations
4//! including superposition, entanglement, and quantum gates.
5
6use rand::Rng;
7use std::collections::{HashMap, HashSet};
8
9/// Simulates a 64-bit quantum memory register with superposition and entanglement capabilities
10pub struct QMem {
11 /// Stores the collapsed bits (0s and 1s)
12 state: u64,
13 /// 1 if bit is in superposition (both 0 and 1), 0 otherwise
14 superposition: u64,
15 /// Entangled pairs (index -> index)
16 entangled: HashMap<usize, usize>,
17 /// Entanglement group mapping
18 entangled_groups: HashMap<usize, HashSet<usize>>,
19}
20
21impl QMem {
22 /// Creates a new quantum memory register with all 64 bits in superposition
23 pub fn new() -> Self {
24 QMem {
25 state: 0,
26 superposition: u64::MAX, // All 64 bits in superposition
27 entangled: HashMap::new(),
28 entangled_groups: HashMap::new(),
29 }
30 }
31
32 /// Sets a qubit to either 0, 1, or superposition
33 ///
34 /// * `index` - The index of the qubit (0-63)
35 /// * `value` - Some(true) for 1, Some(false) for 0, None for superposition
36 pub fn set_bit(&mut self, index: usize, value: Option<bool>) {
37 if index >= 64 {
38 return; // Prevent out-of-bounds access
39 }
40
41 if let Some(v) = value {
42 // Collapse to a fixed value (0 or 1)
43 self.superposition &= !(1 << index); // Clear the superposition bit
44 if v {
45 self.state |= 1 << index; // Set to 1
46 } else {
47 self.state &= !(1 << index); // Set to 0
48 }
49
50 // Collapse entangled groups if they exist
51 self.collapse_entangled_group(index, v);
52 } else {
53 // Set to superposition (both 0 and 1)
54 self.superposition |= 1 << index;
55 }
56 }
57
58 /// Applies the Hadamard Gate (H) to place a qubit in superposition
59 ///
60 /// * `index` - The index of the qubit (0-63)
61 pub fn hadamard(&mut self, index: usize) {
62 self.set_bit(index, None);
63 }
64
65 /// Applies the CNOT Gate: If control is 1, flip the target bit
66 ///
67 /// * `control` - The control qubit index
68 /// * `target` - The target qubit index
69 pub fn cnot(&mut self, control: usize, target: usize) {
70 if self.measure(control) {
71 let target_value = !self.measure(target); // Flip target
72 self.set_bit(target, Some(target_value));
73 }
74 }
75
76 /// Applies the Pauli-X Gate (NOT) to flip the value of a qubit
77 ///
78 /// * `index` - The index of the qubit to flip
79 pub fn pauli_x(&mut self, index: usize) {
80 let current_value = self.measure(index);
81 self.set_bit(index, Some(!current_value));
82 }
83
84 /// Applies the Swap Gate to exchange the values of two qubits
85 ///
86 /// * `a` - The first qubit index
87 /// * `b` - The second qubit index
88 pub fn swap(&mut self, a: usize, b: usize) {
89 if a == b {
90 return; // No need to swap
91 }
92
93 let temp_a = self.measure(a);
94 let temp_b = self.measure(b);
95 self.set_bit(a, Some(temp_b));
96 self.set_bit(b, Some(temp_a));
97 }
98
99 /// Entangles two qubits so their states will always correlate
100 ///
101 /// * `a` - The first qubit index
102 /// * `b` - The second qubit index
103 pub fn entangle(&mut self, a: usize, b: usize) {
104 if a != b {
105 self.entangled.insert(a, b);
106 self.entangled.insert(b, a);
107 }
108 }
109
110 /// Entangles multiple qubits together in a group
111 ///
112 /// * `indices` - Array of qubit indices to entangle
113 pub fn entangle_group(&mut self, indices: &[usize]) {
114 if indices.len() < 2 {
115 return; // Need at least 2 qubits to entangle
116 }
117
118 let mut group = HashSet::new();
119
120 // First collect all existing entanglements
121 for &index in indices {
122 group.insert(index);
123
124 // Merge existing groups if any qubit is already entangled
125 if let Some(existing) = self.entangled_groups.get(&index) {
126 for &member in existing {
127 group.insert(member);
128 }
129 }
130 }
131
132 // Update entanglement for all involved qubits
133 let group_clone = group.clone();
134 for &index in &group {
135 self.entangled_groups.insert(index, group_clone.clone());
136 }
137 }
138
139 /// Collapses all qubits in an entangled group to the same value
140 ///
141 /// * `index` - The index of the qubit that was measured
142 /// * `value` - The value to collapse all entangled qubits to
143 fn collapse_entangled_group(&mut self, index: usize, value: bool) {
144 if let Some(group) = self.entangled_groups.get(&index).cloned() {
145 for &entangled_bit in &group {
146 if entangled_bit != index && (self.superposition >> entangled_bit) & 1 == 1 {
147 // Avoid recursion by directly setting
148 self.superposition &= !(1 << entangled_bit);
149 if value {
150 self.state |= 1 << entangled_bit;
151 } else {
152 self.state &= !(1 << entangled_bit);
153 }
154 }
155 }
156 }
157 // Handle paired entanglement separately from group entanglement
158 if let Some(&pair) = self.entangled.get(&index) {
159 if (self.superposition >> pair) & 1 == 1 {
160 self.superposition &= !(1 << pair);
161 if value {
162 self.state |= 1 << pair;
163 } else {
164 self.state &= !(1 << pair);
165 }
166 }
167 }
168 }
169
170 /// Measures a qubit, collapsing it if in superposition
171 ///
172 /// If in superposition, randomly chooses 0 or 1
173 ///
174 /// * `index` - The index of the qubit to measure
175 /// * Returns the measured value (true for 1, false for 0)
176 pub fn measure(&mut self, index: usize) -> bool {
177 if index >= 64 {
178 return false; // Prevent out-of-bounds access
179 }
180
181 if (self.superposition >> index) & 1 == 1 {
182 // Randomly collapse to 0 or 1 if in superposition
183 let mut rng = rand::rng();
184 let value = rng.random_bool(0.5);
185 self.set_bit(index, Some(value));
186 value
187 } else {
188 // Already collapsed, return the value
189 (self.state >> index) & 1 == 1
190 }
191 }
192
193 /// Runs Bell's Test to check if entangled qubits collapse together
194 ///
195 /// * `a` - The first qubit index
196 /// * `b` - The second qubit index
197 /// * Returns a tuple with the measured values and whether they are correlated
198 pub fn bells_test(&mut self, a: usize, b: usize) -> (bool, bool, bool) {
199 let a_measured = self.measure(a);
200 let b_measured = self.measure(b);
201 let correlated = a_measured == b_measured;
202
203 println!("\nRunning Bell's Test on qubits {} and {}:", a, b);
204 println!("Qubit {}: {}, Qubit {}: {}", a, a_measured, b, b_measured);
205 if correlated {
206 println!("✅ Correlated (Entanglement Verified)");
207 } else {
208 println!("❌ Not Correlated (Possible Decoherence)");
209 }
210
211 (a_measured, b_measured, correlated)
212 }
213
214 /// Print the current state of the quantum memory
215 ///
216 /// Displays the state, superposition, and entanglement information
217 pub fn print(&self) {
218 println!("State: {:064b}", self.state);
219 println!("Superposition: {:064b}", self.superposition);
220 println!("Entanglements: {:?}", self.entangled);
221 println!("Entanglement groups: {:?}", self.entangled_groups);
222 }
223
224 /// Returns the current state value of the quantum register
225 pub fn get_state(&self) -> u64 {
226 self.state
227 }
228
229 /// Returns the current superposition mask of the quantum register
230 pub fn get_superposition(&self) -> u64 {
231 self.superposition
232 }
233
234 /// Returns a reference to the entanglement pairs
235 pub fn get_entangled_pairs(&self) -> &HashMap<usize, usize> {
236 &self.entangled
237 }
238
239 /// Returns a reference to the entanglement groups
240 pub fn get_entangled_groups(&self) -> &HashMap<usize, HashSet<usize>> {
241 &self.entangled_groups
242 }
243}
244
245// Implementing Default trait for QMem
246impl Default for QMem {
247 fn default() -> Self {
248 Self::new()
249 }
250}
251
252#[cfg(test)]
253mod tests {
254 use super::*;
255
256 #[test]
257 fn test_new_qmem() {
258 let qmem = QMem::new();
259 assert_eq!(qmem.state, 0);
260 assert_eq!(qmem.superposition, u64::MAX);
261 assert!(qmem.entangled.is_empty());
262 assert!(qmem.entangled_groups.is_empty());
263 }
264
265 #[test]
266 fn test_set_bit() {
267 let mut qmem = QMem::new();
268 qmem.set_bit(0, Some(true));
269 assert_eq!(qmem.state & 1, 1);
270 assert_eq!(qmem.superposition & 1, 0);
271 }
272
273 #[test]
274 fn test_entangle_and_measure() {
275 let mut qmem = QMem::new();
276 qmem.entangle(0, 1);
277 qmem.set_bit(0, Some(true));
278 assert_eq!(qmem.measure(1), true);
279 }
280}