NN Decryption - Softmax - Very able.
Paste ID: 5704f8ce
Created at: 2026-09-17 08:13:24
Content
First:
"
"""
rune_aes.py
===========
AES-128 (CBC) + SHA-256 keyed cipher + neural network that recovers
a plaintext from a fuzzy ~51% guess.
Produces network_build.gif: one frame every N iterations showing
the network graph evolving and the decrypted message resolving.
Run: python rune_aes.py
Output: network_build.gif
Deps: numpy, pillow, pycryptodome
"""
import os
import math
import json
import time
import hashlib
import secrets
import numpy as np
from PIL import Image, ImageDraw, ImageFont
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
# ============================================================
# CONFIG
# ============================================================
MESSAGE = "The Mandelbrot set hides every secret we could ever need."
FUZZY_ERROR_RATE = 0.49
SEED_STRING = "mandelbrot-2025"
ITERATIONS = 3000
VISUALIZE_EVERY = 25
GIF_PATH = "network_build.gif"
FRAME_DURATION_MS = 120
HIDDEN = [24, 16]
N_FEATURES = 16
FRAME_W = 900
FRAME_H = 620
GRAPH_H = 380
TEXT_H = FRAME_H - GRAPH_H
# ============================================================
# AES-128-SHA CIPHER
# ============================================================
class AES128SHACipher:
"""
Key derivation: SHA-256 of seed string -> first 16 bytes = AES-128 key.
Encryption: AES-128-CBC with random IV (stored in the ciphertext package).
Output: hex-encoded ciphertext per character position is not meaningful
here, so we produce one encrypted block per chunk of plaintext and use
the resulting bytes as the raw material for the neural network.
"""
def __init__(self, seed_string: str):
self.seed_string = seed_string
digest = hashlib.sha256(seed_string.encode("utf-8")).digest()
self.key = digest[:16] # AES-128 key
self.full_digest = digest
def encrypt(self, plaintext: str):
# Pad and encrypt with a random IV
iv = secrets.token_bytes(16)
cipher = AES.new(self.key, AES.MODE_CBC, iv=iv)
ct = cipher.encrypt(pad(plaintext.encode("utf-8"), 16))
# Also produce a per-character SHA hash for the network features.
# Each character's hash is deterministic given (seed, position, char),
# exactly like the Mandelbrot version, but the hash is now SHA-256.
index_card = []
for i, ch in enumerate(plaintext):
h = hashlib.sha256(
"{}|{}|{}".format(self.seed_string, i, ch).encode("utf-8")
).hexdigest()
index_card.append({
"position": i,
"hash": h,
"char": ord(ch),
})
return {
"key_hex": self.key.hex(),
"iv_hex": iv.hex(),
"ciphertext_hex": ct.hex(),
"index_card": index_card,
"plaintext_len": len(plaintext),
}
def decrypt(self, package):
iv = bytes.fromhex(package["iv_hex"])
ct = bytes.fromhex(package["ciphertext_hex"])
cipher = AES.new(self.key, AES.MODE_CBC, iv=iv)
pt = unpad(cipher.decrypt(ct), 16)
return pt.decode("utf-8")
# ============================================================
# FEATURES + ONE-HOT
# ============================================================
def hash_to_features(hash_hex, n_features=16):
raw = bytes.fromhex(hash_hex)
return np.array([b / 255.0 for b in raw[:n_features]], dtype=np.float64)
def char_to_index(ch):
o = ord(ch)
if 97 <= o <= 122: return o - 97
if 65 <= o <= 90: return 26 + (o - 65)
if o == 32: return 52
if 48 <= o <= 57: return 53 + (o - 48)
return 63
def index_to_char(idx):
if 0 <= idx <= 25: return chr(97 + idx)
if 26 <= idx <= 51: return chr(65 + (idx - 26))
if idx == 52: return " "
if 53 <= idx <= 62: return chr(48 + (idx - 53))
return "?"
def char_to_onehot(ch, vocab_size=64):
vec = np.zeros(vocab_size, dtype=np.float64)
vec[char_to_index(ch)] = 1.0
return vec
# ============================================================
# FUZZY GUESS
# ============================================================
def make_fuzzy_guess(message, error_rate, seed=99):
rng = np.random.default_rng(seed)
chars = list(message)
n_errors = int(len(chars) * error_rate)
positions = rng.choice(len(chars), size=n_errors, replace=False)
alphabet = "abcdefghijklmnopqrstuvwxyz .,"
for p in positions:
orig = chars[p]
choices = [c for c in alphabet if c != orig]
chars[p] = choices[rng.integers(0, len(choices))]
return "".join(chars)
# ============================================================
# NETWORK
# ============================================================
class NeuralNetwork:
def __init__(self, layer_sizes, seed=42):
self.layer_sizes = [int(s) for s in layer_sizes]
rng = np.random.default_rng(seed)
self.learning_rate = 0.1
self.momentum = 0.1
self.W, self.b, self.vW, self.vb = [], [], [], []
for i in range(len(self.layer_sizes) - 1):
fan_in = self.layer_sizes[i]
fan_out = self.layer_sizes[i + 1]
scale = math.sqrt(1.0 / max(1, fan_in))
W = rng.normal(0, scale, size=(fan_in, fan_out))
b = np.zeros(fan_out)
self.W.append(W)
self.b.append(b)
self.vW.append(np.zeros_like(W))
self.vb.append(np.zeros_like(b))
self.activations = [np.zeros(s) for s in self.layer_sizes]
self.deltas = [np.zeros(s) for s in self.layer_sizes]
def forward(self, x):
cur = np.asarray(x, dtype=np.float64)
self.activations[0] = cur
for i in range(len(self.W)):
z = cur @ self.W[i] + self.b[i]
if i == len(self.W) - 1:
z_shift = z - np.max(z)
e = np.exp(z_shift)
a = e / np.sum(e)
else:
z = np.clip(z, -15.0, 15.0)
a = 1.0 / (1.0 + np.exp(-z))
self.activations[i + 1] = a
cur = a
return cur
def train_pattern(self, x, target):
x = np.asarray(x, dtype=np.float64)
target = np.asarray(target, dtype=np.float64)
out = self.forward(x)
# Correct gradient descent sign
delta = target - out
self.deltas[-1] = delta
for li in range(len(self.W) - 2, -1, -1):
delta = ((delta @ self.W[li + 1].T)
* self.activations[li + 1]
* (1.0 - self.activations[li + 1]))
self.deltas[li + 1] = delta
for i in range(len(self.W)):
pre = self.activations[i]
d = self.deltas[i + 1]
grad_W = np.outer(pre, d)
self.vW[i] = self.momentum * self.vW[i] + self.learning_rate * grad_W
self.W[i] += self.vW[i]
self.vb[i] = self.momentum * self.vb[i] + self.learning_rate * d
self.b[i] += self.vb[i]
loss = -float(np.sum(target * np.log(out + 1e-12)))
return loss
def predict(self, x):
return self.forward(x)
# ============================================================
# FONTS
# ============================================================
def get_font(size):
candidates = [
"C:/Windows/Fonts/consola.ttf",
"C:/Windows/Fonts/cour.ttf",
"/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf",
"/System/Library/Fonts/Menlo.ttc",
]
for p in candidates:
if os.path.exists(p):
try:
return ImageFont.truetype(p, size)
except Exception:
continue
return ImageFont.load_default()
FONT_12 = get_font(12)
FONT_14 = get_font(14)
FONT_16 = get_font(16)
FONT_18 = get_font(18)
# ============================================================
# FRAME RENDERER
# ============================================================
class FrameRenderer:
def __init__(self, layer_sizes):
self.layer_sizes = layer_sizes
self.n_layers = len(layer_sizes)
self.layer_xs = np.linspace(70, FRAME_W - 70, self.n_layers)
self.positions = []
for li, size in enumerate(layer_sizes):
xs = self.layer_xs[li]
ys = np.linspace(50, GRAPH_H - 40, max(size, 1))
self.positions.append([(float(xs), float(y)) for y in ys])
def render(self, net, iteration, loss, accuracy, message,
wrong_positions, known_positions, burst_flag):
img = Image.new("RGB", (FRAME_W, FRAME_H), (11, 18, 32))
draw = ImageDraw.Draw(img)
for y in range(GRAPH_H, FRAME_H):
shade = 18
draw.line([(0, y), (FRAME_W, y)], fill=(shade, shade + 5, shade + 12))
# Edges
for li in range(len(net.W)):
W = net.W[li]
max_w = max(1e-6, float(np.abs(W).max()))
for i in range(W.shape[0]):
for j in range(W.shape[1]):
w = float(W[i, j])
norm = abs(w) / max_w
if norm < 0.22:
continue
x1, y1 = self.positions[li][i]
x2, y2 = self.positions[li + 1][j]
if w > 0:
a = min(0.85, 0.15 + norm)
color = (int(20 + 54 * a), int(80 + 142 * a), int(40 + 88 * a))
else:
a = min(0.85, 0.15 + norm)
color = (int(160 + 88 * a), int(40 + 33 * a), int(40 + 33 * a))
width = max(1, int(0.4 + 1.8 * norm))
draw.line([(x1, y1), (x2, y2)], fill=color, width=width)
# Neurons
for li, layer_pos in enumerate(self.positions):
acts = net.activations[li]
for ni, (x, y) in enumerate(layer_pos):
a = float(acts[ni]) if ni < len(acts) else 0.0
if li == 0:
base = (56, 189, 248)
elif li == self.n_layers - 1:
base = (245, 158, 11)
else:
base = (167, 139, 250)
glow = 0.20 + 0.80 * min(1.0, a)
r = int(base[0] * glow + 40 * (1 - glow))
g = int(base[1] * glow + 40 * (1 - glow))
b = int(base[2] * glow + 40 * (1 - glow))
radius = int(4 + 5 * min(1.0, a))
draw.ellipse([x - radius, y - radius, x + radius, y + radius],
fill=(r, g, b), outline=(11, 18, 32))
# Header
draw.text((10, 8), "AES-128-SHA Network - Building",
font=FONT_18, fill=(226, 232, 240))
draw.text((10, 30),
"iter {:5d} loss={:.4f} acc={:.1f}%".format(
iteration, loss, accuracy * 100),
font=FONT_14, fill=(148, 163, 184))
# Decryption panel
panel_y = GRAPH_H + 12
draw.text((10, panel_y), "Recovered message:", font=FONT_14,
fill=(148, 163, 184))
panel_y += 22
char_w = 11
line_h = 22
max_chars_per_line = (FRAME_W - 20) // char_w
for idx, ch in enumerate(message):
col = idx % max_chars_per_line
row = idx // max_chars_per_line
x = 10 + col * char_w
y = panel_y + row * line_h
if idx in known_positions:
color = (74, 222, 128)
elif idx in wrong_positions:
color = (248, 113, 113)
else:
color = (96, 165, 250)
draw.text((x, y), ch if ch else " ", font=FONT_16, fill=color)
total_rows = (len(message) // max_chars_per_line) + 1
legend_y = panel_y + total_rows * line_h + 8
draw.text((10, legend_y), "green = known blue = correct red = wrong",
font=FONT_12, fill=(100, 116, 139))
if burst_flag:
draw.text((FRAME_W - 180, legend_y), "[ TARGETED BURST ]",
font=FONT_14, fill=(251, 191, 36))
draw.text((10, FRAME_H - 18),
"AES-128-CBC | SHA-256 key derivation | seed='{}'".format(
SEED_STRING),
font=FONT_12, fill=(71, 85, 105))
return img
# ============================================================
# MAIN
# ============================================================
def build():
message = MESSAGE
print("=" * 70)
print("AES-128-SHA + neural recovery - building {}".format(GIF_PATH))
print("=" * 70)
print("Message: {}".format(message))
print("Seed: {}".format(SEED_STRING))
# --- Encrypt ---
cipher = AES128SHACipher(SEED_STRING)
package = cipher.encrypt(message)
print("\n[Encryption]")
print(" Key (AES-128): {}".format(package["key_hex"]))
print(" IV: {}".format(package["iv_hex"]))
print(" Ciphertext: {} bytes".format(len(package["ciphertext_hex"]) // 2))
print(" Round-trip OK: {}".format(cipher.decrypt(package) == message))
# --- Fuzzy guess ---
fuzzy = make_fuzzy_guess(message, FUZZY_ERROR_RATE)
matches = sum(1 for a, b in zip(message, fuzzy) if a == b)
print("\n[Fuzzy guess]")
print(" Given: {!r}".format(fuzzy))
print(" Match: {}/{} ({:.1f}%)".format(
matches, len(message), matches / len(message) * 100))
# Known positions = wherever the fuzzy guess matches
known_positions = set()
for i, (a, b) in enumerate(zip(message, fuzzy)):
if a == b:
known_positions.add(i)
print(" Known positions: {}/{}".format(len(known_positions), len(message)))
# --- Samples ---
samples = []
for entry in package["index_card"]:
i = entry["position"]
feats = hash_to_features(entry["hash"], n_features=N_FEATURES)
target = char_to_onehot(chr(entry["char"]))
is_known = i in known_positions
samples.append({
"position": i,
"features": feats,
"target": target,
"known": is_known,
"true_char": chr(entry["char"]) if is_known else None,
})
unknown_samples = [s for s in samples if not s["known"]]
# --- Network ---
layer_sizes = [N_FEATURES] + list(HIDDEN) + [64]
net = NeuralNetwork(layer_sizes, seed=42)
renderer = FrameRenderer(layer_sizes)
frames = []
acc_history = []
nudge_active_until = -1
print("\n[Training] {} iterations, frame every {}".format(
ITERATIONS, VISUALIZE_EVERY))
for it in range(ITERATIONS):
order = np.random.permutation(len(samples))
epoch_loss = 0.0
for idx in order:
s = samples[idx]
epoch_loss += net.train_pattern(s["features"], s["target"])
epoch_loss /= max(1, len(samples))
num_correct = 0
wrong_positions = set()
for s in unknown_samples:
pred = net.predict(s["features"])
pred_idx = int(np.argmax(pred))
true_idx = int(np.argmax(s["target"]))
if pred_idx == true_idx:
num_correct += 1
else:
wrong_positions.add(s["position"])
accuracy = num_correct / max(1, len(unknown_samples))
current_chars = []
for s in samples:
if s["known"]:
current_chars.append(s["true_char"])
else:
pred = net.predict(s["features"])
current_chars.append(index_to_char(int(np.argmax(pred))))
current_message = "".join(current_chars)
acc_history.append(accuracy)
burst_flag = False
if len(acc_history) >= 200 and it >= 2000:
prev_best = max(acc_history[-200:-100])
curr_best = max(acc_history[-100:])
if curr_best - prev_best < 0.002 and it > nudge_active_until:
wrong_set = set(wrong_positions)
oversample = list(range(len(samples)))
for _ in range(20):
for i, s in enumerate(samples):
if s["position"] in wrong_set:
oversample.append(i)
for _ in range(80):
np.random.shuffle(oversample)
for idx in oversample:
s = samples[idx]
net.train_pattern(s["features"], s["target"])
nudge_active_until = it + 80
burst_flag = True
if (it + 1) % VISUALIZE_EVERY == 0 or it == ITERATIONS - 1:
img = renderer.render(
net=net, iteration=it + 1, loss=epoch_loss, accuracy=accuracy,
message=current_message, wrong_positions=wrong_positions,
known_positions=known_positions, burst_flag=burst_flag,
)
frames.append(img)
print(" iter {:5d} | loss={:.4f} | acc={:5.1f}% | {!r}".format(
it + 1, epoch_loss, accuracy * 100, current_message))
if not frames:
print("No frames captured.")
return
print("\n[Saving] {} frames to {}".format(len(frames), GIF_PATH))
frames[0].save(
GIF_PATH,
save_all=True,
append_images=frames[1:],
duration=FRAME_DURATION_MS,
loop=0,
optimize=False,
)
size_kb = os.path.getsize(GIF_PATH) / 1024
print("[Done] {} ({:.1f} KB)".format(os.path.abspath(GIF_PATH), size_kb))
if __name__ == "__main__":
build()
"
second page:
"
"""
deeper3.py
==========
Mandelbrot blockchain cipher + brain.js-style neural network that learns
to recover the missing half of an encrypted message, with a live HTML
visualization of the network firing in real time.
Run: python deeper3.py
Output: mandelbrot_live.html (auto-refreshing live view + final report)
A browser tab auto-opens when training finishes.
Dependencies: numpy only (plus stdlib).
"""
import os
import sys
import json
import time
import math
import zlib
import random
import hashlib
import hmac
import webbrowser
import difflib
from typing import Optional, List, Dict, Any, Tuple
import numpy as np
# ============================================================
# CONSTANTS
# ============================================================
LIVE_HTML = "mandelbrot_live.html"
STUCK_WINDOW = 100
STUCK_IMPROVEMENT = 0.002
OVERSAMPLE_FACTOR = 20
BURST_DURATION = 80
BURST_LR_SCALE = 1.0
BURST_MIN_ITERATION = 2000
# ============================================================
# FUZZY PREDICTION
# ============================================================
REFERENCE_SENTENCES = [
"A fractal is a shape that contains itself at every scale.",
"Complex numbers have a real part and an imaginary part.",
"Chaos theory studies how small changes lead to big effects.",
"The butterfly effect is a famous example of sensitive dependence.",
"Iteration is the process of repeating a calculation many times.",
"Boundaries between order and chaos are often fractal in nature.",
"Mathematics reveals patterns that nature hides in plain sight.",
]
def fuzzy_prediction(raw_text):
best_ratio = 0.0
best_match = raw_text
for cand in REFERENCE_SENTENCES:
ratio = difflib.SequenceMatcher(None, raw_text.lower(), cand.lower()).ratio()
if ratio > best_ratio:
best_ratio = ratio
best_match = cand
return best_match, best_ratio
# ============================================================
# MANDEBROT CIPHER
# ============================================================
class MandelbrotSVGScaler:
MAX_ALLOWED_DEPTH = 300
def __init__(self):
self.max_depth = 300
self.precision = 1_000_000
@staticmethod
def _crc32(data: bytes) -> int:
return zlib.crc32(data) & 0xFFFFFFFF
@staticmethod
def _make_rng(seed_value: int):
return random.Random(seed_value)
def generate_scaled_location(self, seed, char, iteration_limit=1000):
depth = int(getattr(self, "max_depth", 30))
if depth < 1 or depth > self.MAX_ALLOWED_DEPTH:
depth = self.MAX_ALLOWED_DEPTH
depth = max(1, min(self.MAX_ALLOWED_DEPTH, depth))
seed_bytes = (str(seed) + char).encode("utf-8")
rng = self._make_rng(self._crc32(seed_bytes))
x0 = rng.randint(-2000, 1000) / 1000
y0 = rng.randint(-1500, 1500) / 1000
zoom_level = int(rng.randint(1, depth))
zoom_level = max(1, min(self.MAX_ALLOWED_DEPTH, zoom_level))
zoom = float(2 ** zoom_level)
pixel_x = rng.randint(0, 800)
pixel_y = rng.randint(0, 600)
width = 3.0 / zoom
height = 3.0 / zoom
real = x0 + (pixel_x / 800 * width - (width / 2))
imag = y0 + (pixel_y / 600 * height - (height / 2))
real_scaled = round(real * self.precision)
imag_scaled = round(imag * self.precision)
zr, zi = 0.0, 0.0
iterations = 0
while zr * zr + zi * zi < 4 and iterations < iteration_limit:
temp = zr * zr - zi * zi + real
zi = 2 * zr * zi + imag
zr = temp
iterations += 1
return {
"real": real, "imag": imag,
"realScaled": real_scaled, "imagScaled": imag_scaled,
"zoom": zoom_level, "iterations": iterations,
"pixelX": pixel_x, "pixelY": pixel_y,
}
def generate_unique_hash(self, location, char):
unique_data = "|".join([
str(location["realScaled"]), str(location["imagScaled"]),
str(location["zoom"]), str(location["iterations"]),
str(ord(char)),
])
return hashlib.sha512(unique_data.encode("utf-8")).hexdigest()
def visualize_mandelbrot_point(self, location, size=300):
real = location["real"]
imag = location["imag"]
return (
f'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {size} {size}" '
f'width="{size}" height="{size}">'
f'<rect width="100%" height="100%" fill="#000" />'
f'<circle cx="{size/2}" cy="{size/2}" r="3" fill="red" />'
f'<text x="5" y="15" fill="white" font-size="10">Real: {real:.8f}</text>'
f'<text x="5" y="30" fill="white" font-size="10">Imag: {imag:.8f}</text>'
f'<text x="5" y="45" fill="white" font-size="10">Zoom: {location["zoom"]}x</text>'
f'</svg>'
)
class MandelbrotBlockchainCipher:
def __init__(self, seed: Optional[int] = None, difficulty: int = 2):
self.max_iterations = 10000
self.difficulty = max(1, min(4, int(difficulty)))
self.seed = seed if seed is not None else int(time.time())
self.svg_scaler = MandelbrotSVGScaler()
def encrypt(self, plaintext):
index_card = []
hashes = []
blockchain = []
prev_hash = "0" * 64
for index, char in enumerate(plaintext):
location = self.svg_scaler.generate_scaled_location(
"{}{}".format(self.seed, index), char)
h = self.svg_scaler.generate_unique_hash(location, char)
hashes.append(h)
index_card.append({
"location": location, "hash": h,
"char": ord(char),
"svg": self.svg_scaler.visualize_mandelbrot_point(location),
})
mega_hash = self._create_mega_hash(hashes)
block_data = []
for index, mapping in enumerate(index_card):
mac = self._create_hmac(mapping["hash"], mega_hash)
index_card[index]["hmac"] = mac
block_data.append({
"char": mapping["char"], "hash": mapping["hash"], "hmac": mac,
"location": {
"real": mapping["location"]["real"],
"imag": mapping["location"]["imag"],
"zoom": mapping["location"]["zoom"],
"iterations": mapping["location"]["iterations"],
},
})
if len(block_data) == 5 or index == len(index_card) - 1:
block = self._mine_block(prev_hash, block_data, self.difficulty)
blockchain.append(block)
prev_hash = block["hash"]
block_data = []
return {
"seed": self.seed, "indexCard": index_card,
"megaHash": mega_hash, "blockchain": blockchain,
"timestamp": int(time.time()),
}
def _create_mega_hash(self, hashes):
return hashlib.sha512("".join(hashes).encode("utf-8")).hexdigest()
def _create_hmac(self, h, mega_hash):
return hmac.new(
mega_hash.encode("utf-8"), h.encode("utf-8"), hashlib.md5
).hexdigest()
def _mine_block(self, prev_hash, data, difficulty):
nonce = 0
prefix = "0" * difficulty
start_time = time.time()
while True:
block_data = prev_hash + json.dumps(data, separators=(",", ":")) + str(nonce)
h = hashlib.sha256(block_data.encode("utf-8")).hexdigest()
if h.startswith(prefix):
return {"hash": h, "prevHash": prev_hash, "data": data,
"nonce": nonce, "timestamp": int(time.time())}
nonce += 1
if nonce % 20000 == 0 and (time.time() - start_time) > 2:
difficulty -= 1
prefix = "0" * max(1, difficulty)
if difficulty < 1:
return {"hash": h, "prevHash": prev_hash, "data": data,
"nonce": nonce, "timestamp": int(time.time()),
"note": "Mining timeout - difficulty reduced"}
def decrypt(self, encrypted_package):
if not self._verify_blockchain(encrypted_package["blockchain"]):
return "ERROR: Blockchain integrity check failed"
all_hashes = [m["hash"] for m in encrypted_package["indexCard"]]
if self._create_mega_hash(all_hashes) != encrypted_package["megaHash"]:
return "ERROR: MegaHash verification failed"
out = []
for mapping in encrypted_package["indexCard"]:
calc = self._create_hmac(mapping["hash"], encrypted_package["megaHash"])
if calc != mapping["hmac"]:
return "ERROR: HMAC verification failed for character"
out.append(chr(mapping["char"]))
return "".join(out)
def _verify_blockchain(self, blockchain):
prev_hash = "0" * 64
for block in blockchain:
if block["prevHash"] != prev_hash:
return False
bd = (block["prevHash"]
+ json.dumps(block["data"], separators=(",", ":"))
+ str(block["nonce"]))
if hashlib.sha256(bd.encode("utf-8")).hexdigest() != block["hash"]:
return False
prev_hash = block["hash"]
return True
# ============================================================
# HASH -> FEATURES, CHAR <-> ONE-HOT
# ============================================================
def hash_to_features(hash_hex: str, n_features: int = 16) -> np.ndarray:
raw = bytes.fromhex(hash_hex)
return np.array([b / 255.0 for b in raw[:n_features]], dtype=np.float64)
def char_to_index(ch: str) -> int:
o = ord(ch)
if 97 <= o <= 122:
return o - 97
if 65 <= o <= 90:
return 26 + (o - 65)
if o == 32:
return 52
if 48 <= o <= 57:
return 53 + (o - 48)
return 63
def index_to_char(idx: int) -> str:
if 0 <= idx <= 25:
return chr(97 + idx)
if 26 <= idx <= 51:
return chr(65 + (idx - 26))
if idx == 52:
return " "
if 53 <= idx <= 62:
return chr(48 + (idx - 53))
return "?"
def char_to_onehot(ch: str, vocab_size: int = 64) -> np.ndarray:
idx = char_to_index(ch)
vec = np.zeros(vocab_size, dtype=np.float64)
vec[idx] = 1.0
return vec
# ============================================================
# LIVE NEURAL NETWORK
# ============================================================
class LiveNeuralNetwork:
def __init__(self, layer_sizes, seed=42):
self.layer_sizes = [int(s) for s in layer_sizes]
self.rng = np.random.default_rng(seed)
self.learning_rate = 0.1
self.momentum = 0.1
self.error_thresh = 0.005
self.W = []
self.b = []
self.vW = []
self.vb = []
for i in range(len(self.layer_sizes) - 1):
fan_in = self.layer_sizes[i]
fan_out = self.layer_sizes[i + 1]
scale = math.sqrt(1.0 / max(1, fan_in))
W = self.rng.normal(0, scale, size=(fan_in, fan_out))
b = np.zeros(fan_out)
self.W.append(W)
self.b.append(b)
self.vW.append(np.zeros_like(W))
self.vb.append(np.zeros_like(b))
self.activations = [np.zeros(s) for s in self.layer_sizes]
self.deltas = [np.zeros(s) for s in self.layer_sizes]
print("[fwd] acts:", [round(float(np.mean(a)),4) for a in self.activations])
def forward(self, x):
cur = np.asarray(x, dtype=np.float64)
self.activations[0] = cur
for i in range(len(self.W)):
z = cur @ self.W[i] + self.b[i]
if i == len(self.W) - 1:
z_shift = z - np.max(z)
e = np.exp(z_shift)
a = e / np.sum(e)
else:
z = np.clip(z, -15.0, 15.0)
a = 1.0 / (1.0 + np.exp(-z))
self.activations[i + 1] = a
cur = a
return cur
def train_pattern(self, x, target):
x = np.asarray(x, dtype=np.float64)
target = np.asarray(target, dtype=np.float64)
out = self.forward(x)
if not hasattr(self, "_dbg"):
true_idx = int(np.argmax(target))
print("[dbg] true class:", true_idx, "predicted prob for it:", float(out[true_idx]))
print("[dbg] max prob class:", int(np.argmax(out)), "value:", float(out.max()))
print("[dbg] out[:5]:", ["{:.4f}".format(float(v)) for v in out[:5]])
print("[dbg] target argmax:", true_idx)
print("[dbg] W0 first row:", ["{:.4f}".format(float(v)) for v in self.W[0][0][:5]])
self._dbg = True
delta = target - out
self.deltas[-1] = delta
for li in range(len(self.W) - 2, -1, -1):
delta = ((delta @ self.W[li + 1].T)
* self.activations[li + 1]
* (1.0 - self.activations[li + 1]))
self.deltas[li + 1] = delta
for i in range(len(self.W)):
pre = self.activations[i]
d = self.deltas[i + 1]
grad_W = np.outer(pre, d)
self.vW[i] = self.momentum * self.vW[i] + self.learning_rate * grad_W
self.W[i] += self.vW[i]
self.vb[i] = self.momentum * self.vb[i] + self.learning_rate * d
self.b[i] += self.vb[i]
loss = -float(np.sum(target * np.log(out + 1e-12)))
return loss
def predict(self, x):
return self.forward(x)
# ============================================================
# LIVE VISUALIZER
# ============================================================
def _esc(s):
return (str(s).replace("&", "&")
.replace("<", "<")
.replace(">", ">")
.replace('"', """))
LIVE_TEMPLATE = """<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Mandelbrot Network - Live</title>
<meta http-equiv="refresh" content="{refresh_ms}">
<style>
:root {{ --panel:#121a2b; --text:#e2e8f0; --muted:#94a3b8; }}
* {{ box-sizing: border-box; }}
body {{
margin:0; padding: 24px;
background: radial-gradient(1200px 600px at 50% -10%, #17223a, #0b1220 60%);
color: var(--text);
font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
line-height: 1.5;
}}
h1 {{ font-size: 22px; margin: 0 0 4px; }}
h2 {{ font-size: 13px; margin: 20px 0 8px; color: var(--muted);
text-transform: uppercase; letter-spacing: 0.08em; }}
.sub {{ color: var(--muted); font-size: 13px; margin-bottom: 20px; }}
.grid {{ display: grid; grid-template-columns: repeat(auto-fit, minmax(180px,1fr));
gap: 12px; margin-bottom: 16px; }}
.metric {{ background: var(--panel); border: 1px solid #22304a;
border-radius: 10px; padding: 12px 14px; }}
.metric .label {{ color: var(--muted); font-size: 11px;
text-transform: uppercase; letter-spacing: 0.06em; }}
.metric .value {{ font-size: 22px; font-weight: 600; margin-top: 4px; }}
.card {{ background: var(--panel); border: 1px solid #22304a;
border-radius: 12px; padding: 16px; margin-top: 12px; }}
.pred-row {{ display: flex; justify-content: space-between;
padding: 6px 0; border-bottom: 1px solid #1e2a3f; font-size: 13px; }}
.pred-row:last-child {{ border-bottom: none; }}
.pred-row .label {{ color: var(--muted); }}
.pred-row .val {{ font-family: monospace; }}
code {{ background: #0e1526; padding: 2px 6px; border-radius: 4px; font-size: 12px; }}
.legend {{ display: flex; gap: 14px; font-size: 12px; color: var(--muted); margin-top: 8px; }}
.dot {{ display: inline-block; width: 9px; height: 9px; border-radius: 50%;
margin-right: 6px; vertical-align: middle; }}
</style>
</head>
<body>
<h1>Mandelbrot Network - Live Training</h1>
<div class="sub">Page auto-refreshes every {refresh_ms} ms. Neurons glow as they fire;
edges thicken as weights strengthen.</div>
<div class="grid">
<div class="metric"><div class="label">Trial</div><div class="value">{trial}</div></div>
<div class="metric"><div class="label">Loss</div><div class="value">{loss:.4f}</div></div>
<div class="metric"><div class="label">Accuracy</div><div class="value">{accuracy:.1f}%</div></div>
<div class="metric"><div class="label">Neurons</div><div class="value">{n_neurons}</div></div>
<div class="metric"><div class="label">Synapses</div><div class="value">{n_syn}</div></div>
</div>
<div class="card">
<h2 style="margin-top:0">Network</h2>
<svg viewBox="0 0 {svg_w} {svg_h}" style="width:100%;height:auto;display:block;
background:#0b1220;border-radius:8px">{edges}{neurons}</svg>
<div class="legend">
<span><span class="dot" style="background:#38bdf8"></span>Input</span>
<span><span class="dot" style="background:#a78bfa"></span>Hidden</span>
<span><span class="dot" style="background:#f59e0b"></span>Output</span>
<span>green edges = positive weight, red = negative</span>
</div>
</div>
<div class="card">
<h2 style="margin-top:0">Last prediction</h2>
{pred_html}
</div>
<div class="card">
<h2 style="margin-top:0">Loss</h2>
{loss_svg}
</div>
<div class="card">
<h2 style="margin-top:0">Accuracy</h2>
{acc_svg}
</div>
</body>
</html>
"""
class LiveVisualizer:
def __init__(self, net, path=LIVE_HTML):
self.net = net
self.path = path
self.trial_history = []
self.loss_history = []
self.accuracy_history = []
self.last_prediction = ""
self.last_expected = ""
def record(self, trial, loss, accuracy, prediction, expected):
self.trial_history.append(int(trial))
self.loss_history.append(float(loss))
self.accuracy_history.append(float(accuracy))
self.last_prediction = prediction
self.last_expected = expected
def _sparkline(self, values, width=800, height=100, color="#4ade80"):
if not values:
return "<svg></svg>"
vmin, vmax = min(values), max(values)
if vmax == vmin:
vmax = vmin + 1e-9
n = len(values)
pts = []
for i, v in enumerate(values):
x = (i / max(1, n - 1)) * width
y = height - ((v - vmin) / (vmax - vmin)) * (height - 20) - 10
pts.append("{:.1f},{:.1f}".format(x, y))
poly = " ".join(pts)
return (
'<svg viewBox="0 0 {w} {h}" preserveAspectRatio="none" '
'style="width:100%;height:{h}px;display:block">'
'<polyline points="{p}" fill="none" stroke="{c}" stroke-width="2"/>'
'</svg>'
).format(w=width, h=height, p=poly, c=color)
def render(self):
net = self.net
layers = net.layer_sizes
n_layers = len(layers)
svg_w, svg_h = 900, 400
layer_xs = np.linspace(80, svg_w - 80, n_layers)
positions = []
for li, size in enumerate(layers):
xs = layer_xs[li]
ys = np.linspace(60, svg_h - 40, max(size, 1))
positions.append([(float(xs), float(y)) for y in ys])
edges = []
for li in range(len(net.W)):
W = net.W[li]
max_w = max(1e-6, float(np.abs(W).max()))
for i in range(W.shape[0]):
for j in range(W.shape[1]):
w = float(W[i, j])
norm = abs(w) / max_w
if norm < 0.15:
continue
x1, y1 = positions[li][i]
x2, y2 = positions[li + 1][j]
if w > 0:
color = "rgba(74,222,128,{:.2f})".format(min(0.9, norm))
else:
color = "rgba(248,113,113,{:.2f})".format(min(0.9, norm))
sw = 0.3 + 2.0 * norm
edges.append(
'<line x1="{:.1f}" y1="{:.1f}" x2="{:.1f}" y2="{:.1f}" '
'stroke="{}" stroke-width="{:.2f}"/>'.format(
x1, y1, x2, y2, color, sw)
)
neurons = []
for li, layer_pos in enumerate(positions):
activations = net.activations[li]
for ni, (x, y) in enumerate(layer_pos):
a = float(activations[ni]) if ni < len(activations) else 0.0
if li == 0:
base = (56, 189, 248)
elif li == n_layers - 1:
base = (245, 158, 11)
else:
base = (167, 139, 250)
glow = 0.25 + 0.75 * min(1.0, a)
r = int(base[0] * glow + 40 * (1 - glow))
g = int(base[1] * glow + 40 * (1 - glow))
b = int(base[2] * glow + 40 * (1 - glow))
radius = 5 + 6 * min(1.0, a)
neurons.append(
'<circle cx="{:.1f}" cy="{:.1f}" r="{:.1f}" '
'fill="rgb({},{},{})" stroke="#0b1220" stroke-width="1"/>'.format(
x, y, radius, r, g, b)
)
loss_svg = self._sparkline(self.loss_history, color="#4ade80")
acc_svg = self._sparkline(self.accuracy_history, color="#60a5fa")
pred_html = (
'<div class="pred-row">'
'<span class="label">expected</span>'
'<span class="val">' + _esc(self.last_expected) + '</span>'
'</div>'
'<div class="pred-row">'
'<span class="label">predicted</span>'
'<span class="val">' + _esc(self.last_prediction) + '</span>'
'</div>'
)
last_loss = self.loss_history[-1] if self.loss_history else 0.0
last_acc = self.accuracy_history[-1] if self.accuracy_history else 0.0
trial = self.trial_history[-1] if self.trial_history else 0
html_out = LIVE_TEMPLATE.format(
svg_w=svg_w, svg_h=svg_h,
edges="".join(edges),
neurons="".join(neurons),
loss_svg=loss_svg,
acc_svg=acc_svg,
pred_html=pred_html,
trial=trial,
loss=last_loss,
accuracy=last_acc * 100.0,
n_syn=int(sum(W.size for W in net.W)),
n_neurons=int(sum(layers)),
refresh_ms=2000,
)
tmp = self.path + ".tmp"
with open(tmp, "w", encoding="utf-8") as f:
f.write(html_out)
os.replace(tmp, self.path)
# ============================================================
# TRAINING
# ============================================================
def train_on_ciphertext(message: str,
known_half: str,
assume_prefix: bool = True,
n_features: int = 16,
hidden: List[int] = None,
iterations: int = 1500,
seed: int = 7,
difficulty: int = 2,
visualize_every: int = 25,
verbose: bool = True):
if hidden is None:
hidden = [24, 16]
print("=" * 70)
print("Mandelbrot Network - cipher + solver + live visualization")
print("=" * 70)
cipher = MandelbrotBlockchainCipher(seed=seed, difficulty=difficulty)
print("\n[1/4] Encrypting message ({} chars) with seed={} difficulty={}...".format(
len(message), seed, cipher.difficulty))
t0 = time.time()
encrypted = cipher.encrypt(message)
print(" Done in {:.3f}s. {} blocks mined.".format(
time.time() - t0, len(encrypted["blockchain"])))
total_len = len(message)
known_len = len(known_half)
if assume_prefix:
known_positions = set(range(known_len))
else:
known_positions = set(range(total_len - known_len, total_len))
print("\n[2/4] Building training data...")
print(" Known positions: {}/{}".format(len(known_positions), total_len))
samples = []
for i, entry in enumerate(encrypted["indexCard"]):
feats = hash_to_features(entry["hash"], n_features=n_features)
target = char_to_onehot(chr(entry["char"]))
is_known = i in known_positions
samples.append({
"position": i,
"features": feats,
"target": target,
"known": is_known,
"true_char": chr(entry["char"]) if is_known else None,
})
unknown_samples = [s for s in samples if not s["known"]]
print(" Total samples: {}, unknown: {}".format(
len(samples), len(unknown_samples)))
layer_sizes = [n_features] + list(hidden) + [64]
print("\n[3/4] Building network: {}".format(layer_sizes))
net = LiveNeuralNetwork(layer_sizes, seed=42)
visualizer = LiveVisualizer(net, path=LIVE_HTML)
print("\n[4/4] Training ({} iterations, visualizing every {})...".format(
iterations, visualize_every))
print(" Live view: {}".format(os.path.abspath(LIVE_HTML)))
acc_history = []
nudge_active_until = -1
nudge_count = 0
for it in range(iterations):
order = np.random.permutation(len(samples))
epoch_loss = 0.0
for idx in order:
s = samples[idx]
epoch_loss += net.train_pattern(s["features"], s["target"])
epoch_loss /= max(1, len(samples))
num_correct = 0
last_pred_char = ""
last_true_char = ""
wrong_positions = []
for s in unknown_samples:
pred = net.predict(s["features"])
pred_idx = int(np.argmax(pred))
true_idx = int(np.argmax(s["target"]))
if pred_idx == true_idx:
num_correct += 1
else:
wrong_positions.append(s["position"])
last_pred_char = index_to_char(pred_idx)
last_true_char = index_to_char(true_idx)
accuracy = num_correct / max(1, len(unknown_samples))
acc_history.append(accuracy)
if len(acc_history) >= 2 * STUCK_WINDOW:
prev_best = max(acc_history[:STUCK_WINDOW])
curr_best = max(acc_history[STUCK_WINDOW:])
improvement = curr_best - prev_best
if it < BURST_MIN_ITERATION:
acc_history[:] = acc_history[STUCK_WINDOW:]
elif improvement < STUCK_IMPROVEMENT and it > nudge_active_until and wrong_positions:
wrong_set = set(wrong_positions)
oversample_indices = list(range(len(samples)))
for _ in range(OVERSAMPLE_FACTOR):
for i, s in enumerate(samples):
if s["position"] in wrong_set:
oversample_indices.append(i)
old_lr = net.learning_rate
net.learning_rate = old_lr * BURST_LR_SCALE
for _ in range(BURST_DURATION):
np.random.shuffle(oversample_indices)
for idx in oversample_indices:
s = samples[idx]
net.train_pattern(s["features"], s["target"])
net.learning_rate = old_lr
nudge_active_until = it + BURST_DURATION
nudge_count += 1
if verbose:
print(" [{:5d}] STUCK #{} (best {:.3f}->{:.3f}) | "
"wrong at {} | oversample {}x for {} iters".format(
it + 1, nudge_count, prev_best, curr_best,
wrong_positions, OVERSAMPLE_FACTOR,
BURST_DURATION))
acc_history[:] = acc_history[STUCK_WINDOW:]
visualizer.record(it + 1, epoch_loss, accuracy,
last_pred_char, last_true_char)
if (it + 1) % visualize_every == 0:
visualizer.render()
if verbose:
print(" iter {:5d} | loss={:.4f} | unknown_acc={:5.1f}% | ({}/{})".format(
it + 1, epoch_loss, accuracy * 100,
num_correct, len(unknown_samples)))
visualizer.render()
print("\nTraining complete. Live view: {}".format(os.path.abspath(LIVE_HTML)))
predicted_message = []
for s in samples:
if s["known"]:
predicted_message.append(s["true_char"])
else:
pred = net.predict(s["features"])
predicted_message.append(index_to_char(int(np.argmax(pred))))
predicted_message = "".join(predicted_message)
print("\nTrue message: {!r}".format(message))
print("Predicted message: {!r}".format(predicted_message))
matches = sum(1 for a, b in zip(message, predicted_message) if a == b)
print("Match: {}/{} ({:.1f}%)".format(
matches, len(message), matches / len(message) * 100))
fuzzy, ratio = fuzzy_prediction(predicted_message)
print("\nFuzzy prediction: {!r}".format(fuzzy))
print("Similarity: {:.1%}".format(ratio))
return net, encrypted, predicted_message, visualizer
# ============================================================
# MAIN
# ============================================================
if __name__ == "__main__":
message = "The Mandelbrot set hides every secret we could ever need. And nomes fly, if you walk through them."
known = message[:len(message) // 2]
print("Full message: {!r}".format(message))
print("Known prefix: {!r}".format(known))
print()
net, encrypted, predicted, viz = train_on_ciphertext(
message=message,
known_half=known,
assume_prefix=True,
n_features=16,
hidden=[24, 16],
iterations=1500,
seed=7,
difficulty=2,
visualize_every=25,
verbose=True,
)
report_path = os.path.abspath(LIVE_HTML)
url = "file:///" + report_path.replace("\\", "/")
print("\nOpening report: {}".format(url))
try:
webbrowser.open(url)
except Exception as e:
print("Could not auto-open browser: {}".format(e))
print("Open this file manually: {}".format(report_path))
"
End of File Transmission. GL