Spaces:
Sleeping
Sleeping
Update tab/tab6_noise_simulation.py
Browse files- tab/tab6_noise_simulation.py +48 -20
tab/tab6_noise_simulation.py
CHANGED
|
@@ -4,38 +4,66 @@ from io import BytesIO
|
|
| 4 |
from PIL import Image
|
| 5 |
import random
|
| 6 |
|
| 7 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
bits = list(key_str.strip())
|
| 9 |
total_bits = len(bits)
|
| 10 |
num_flips = int(total_bits * flip_percent)
|
|
|
|
|
|
|
| 11 |
flip_indices = random.sample(range(total_bits), num_flips)
|
|
|
|
| 12 |
for i in flip_indices:
|
| 13 |
-
bits[i] = '1' if bits[i] == '0' else '0'
|
| 14 |
-
|
|
|
|
|
|
|
| 15 |
|
|
|
|
| 16 |
def compare_original_vs_noisy(key_str):
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
axs[1].set_xlabel("Bit Index")
|
| 24 |
-
axs[
|
| 25 |
-
axs[1].set_ylabel("Bit
|
|
|
|
| 26 |
plt.tight_layout()
|
|
|
|
|
|
|
| 27 |
buf = BytesIO()
|
| 28 |
plt.savefig(buf, format='png')
|
| 29 |
plt.close()
|
| 30 |
buf.seek(0)
|
| 31 |
-
return Image.open(buf)
|
| 32 |
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
noise_btn = gr.Button("Simulate Eavesdropper")
|
| 37 |
-
noise_graph = gr.Image(label="Original vs Noisy")
|
| 38 |
|
| 39 |
-
|
| 40 |
-
inputs=[original_input],
|
| 41 |
-
outputs=[noise_graph])
|
|
|
|
| 4 |
from PIL import Image
|
| 5 |
import random
|
| 6 |
|
| 7 |
+
# ---------------- Function to add random noise (simulate eavesdropper) ----------------
|
| 8 |
+
def add_noise_to_key(key_str, flip_percent=0.1):
|
| 9 |
+
"""
|
| 10 |
+
Flips 'flip_percent' of bits in the key to simulate eavesdropper noise.
|
| 11 |
+
"""
|
| 12 |
bits = list(key_str.strip())
|
| 13 |
total_bits = len(bits)
|
| 14 |
num_flips = int(total_bits * flip_percent)
|
| 15 |
+
|
| 16 |
+
# Randomly select positions to flip
|
| 17 |
flip_indices = random.sample(range(total_bits), num_flips)
|
| 18 |
+
|
| 19 |
for i in flip_indices:
|
| 20 |
+
bits[i] = '1' if bits[i] == '0' else '0' # Flip the bit
|
| 21 |
+
|
| 22 |
+
return ''.join(bits), flip_indices # Also return which bits were flipped
|
| 23 |
+
|
| 24 |
|
| 25 |
+
# ---------------- Function to compare and plot ----------------
|
| 26 |
def compare_original_vs_noisy(key_str):
|
| 27 |
+
"""
|
| 28 |
+
Compares original and noisy QKD keys with a visual plot.
|
| 29 |
+
Highlights flipped bits for clarity.
|
| 30 |
+
"""
|
| 31 |
+
key_str = ''.join([b for b in key_str.strip() if b in '01']) # Clean input
|
| 32 |
+
if not key_str:
|
| 33 |
+
return None, "⚠️ Invalid input: Please enter a binary key."
|
| 34 |
+
|
| 35 |
+
noisy_key, flipped_indices = add_noise_to_key(key_str)
|
| 36 |
+
|
| 37 |
+
total_bits = len(key_str)
|
| 38 |
+
heights = [1] * total_bits # Fixed height bars
|
| 39 |
+
x = range(total_bits)
|
| 40 |
+
|
| 41 |
+
fig, axs = plt.subplots(2, 1, figsize=(12, 3.8), sharex=True)
|
| 42 |
+
|
| 43 |
+
# ---------------- First plot: Original Key (all green) ----------------
|
| 44 |
+
axs[0].bar(x, heights, color='green', edgecolor='black', linewidth=0.2)
|
| 45 |
+
axs[0].set_title("✅ Before Noise: Original QKD Key", fontsize=11)
|
| 46 |
+
axs[0].set_yticks([])
|
| 47 |
+
axs[0].set_ylabel("Bit")
|
| 48 |
+
|
| 49 |
+
# ---------------- Second plot: Noisy Key (red where flipped, green where same) ----------------
|
| 50 |
+
colors = ['red' if i in flipped_indices else 'green' for i in range(total_bits)]
|
| 51 |
+
axs[1].bar(x, heights, color=colors, edgecolor='black', linewidth=0.2)
|
| 52 |
+
axs[1].set_title("❌ After Noise: Key with Eavesdropper Flips", fontsize=11)
|
| 53 |
axs[1].set_xlabel("Bit Index")
|
| 54 |
+
axs[1].set_yticks([])
|
| 55 |
+
axs[1].set_ylabel("Bit")
|
| 56 |
+
|
| 57 |
plt.tight_layout()
|
| 58 |
+
|
| 59 |
+
# Save to buffer and return
|
| 60 |
buf = BytesIO()
|
| 61 |
plt.savefig(buf, format='png')
|
| 62 |
plt.close()
|
| 63 |
buf.seek(0)
|
|
|
|
| 64 |
|
| 65 |
+
# Generate human-readable summary
|
| 66 |
+
corruption_rate = (len(flipped_indices) / total_bits) * 100
|
| 67 |
+
summary = f"⚠️ {len(flipped_indices)} bits flipped out of {total_bits} — {corruption_rate:.2f}% corruption detected."
|
|
|
|
|
|
|
| 68 |
|
| 69 |
+
return Image.open(buf), summary
|
|
|
|
|
|