Quazim0t0 commited on
Commit
fbb5ab1
·
verified ·
1 Parent(s): aa7bd25

Upload fractal.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. fractal.py +79 -0
fractal.py ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ fractal.py -- Mandelbrot phase seeding for Quazimoto-LM's oscillator bank.
3
+
4
+ The recommended (and only) fractal integration: instead of a generic learned
5
+ phase initializer, give each TOKEN a characteristic dynamical signature drawn
6
+ from the Mandelbrot iteration z <- z^2 + c, and use the ANGLES of that orbit to
7
+ seed the N oscillator phases. The Mandelbrot map is itself an iterated dynamical
8
+ system, so this hands the Kuramoto ring bank a token-specific, deterministic,
9
+ parameter-free phase prior congruent with what the block already does.
10
+
11
+ We build a frozen [vocab_size, n_osc] table once: token id -> a complex point c
12
+ (spread over the Mandelbrot region by a 2D Halton low-discrepancy sequence so
13
+ coverage is even and deterministic) -> phase_k = angle(z_k) for the first n_osc
14
+ orbit points. The model adds this, through a zero-init gate, to to_theta(h) inside
15
+ each QuazimotoBlock -- a no-op at init that the optimizer can choose to open.
16
+
17
+ Smooth-by-construction: we read the orbit ANGLE (always defined, bounded to
18
+ (-pi, pi]) rather than escape-time, avoiding the chaotic boundary discontinuities
19
+ that raw escape counts would inject.
20
+ """
21
+
22
+ import torch
23
+
24
+
25
+ def _halton(i, base):
26
+ """Radical-inverse (van der Corput) value of i in the given base, in [0,1)."""
27
+ f, r = 1.0, 0.0
28
+ while i > 0:
29
+ f /= base
30
+ r += f * (i % base)
31
+ i //= base
32
+ return r
33
+
34
+
35
+ @torch.no_grad()
36
+ def mandelbrot_phase_table(vocab_size, n_osc, region=(-2.5, 1.0, -1.25, 1.25),
37
+ clamp_mag=1e3):
38
+ """Return a frozen [vocab_size, n_osc] tensor of orbit-angle phase seeds.
39
+
40
+ token id -> c via 2D Halton(base 2,3) over `region`; phase_k = angle(z_k) for
41
+ k = 0..n_osc-1 of the iteration z <- z^2 + c (z0 = 0). This is the FLAT
42
+ (tokenizer-agnostic) map; for the hierarchical byte-merge map build the table
43
+ offline with build_fractal_table.py and load it via load_phase_table()."""
44
+ x0, x1, y0, y1 = region
45
+ ids = torch.arange(1, vocab_size + 1)
46
+ hx = torch.tensor([_halton(int(i), 2) for i in ids])
47
+ hy = torch.tensor([_halton(int(i), 3) for i in ids])
48
+ cr = x0 + hx * (x1 - x0)
49
+ ci = y0 + hy * (y1 - y0)
50
+ return phases_from_c(torch.complex(cr, ci), n_osc, clamp_mag)
51
+
52
+
53
+ @torch.no_grad()
54
+ def phases_from_c(c, n_osc, clamp_mag=1e3):
55
+ """Orbit-angle phases for a batch of complex seeds c [V] -> [V, n_osc].
56
+ phase_k = angle(z_k) of z <- z^2 + c (z0=0); magnitude clamped (angle kept)."""
57
+ z = torch.zeros_like(c)
58
+ phases = torch.empty(c.shape[0], n_osc)
59
+ for k in range(n_osc):
60
+ z = z * z + c
61
+ mag = z.abs()
62
+ over = mag > clamp_mag # rescale escaped orbits, keep direction
63
+ if over.any():
64
+ z = torch.where(over, z / mag * clamp_mag, z)
65
+ phases[:, k] = torch.angle(z) # in (-pi, pi]
66
+ return phases
67
+
68
+
69
+ def load_phase_table(vocab_size, n_osc, path):
70
+ """Load a precomputed phase table if it matches (vocab_size, n_osc); else None.
71
+ Returns (phases, mode) or (None, None)."""
72
+ import os
73
+ if not os.path.exists(path):
74
+ return None, None
75
+ d = torch.load(path, map_location="cpu", weights_only=False)
76
+ ph = d.get("phases")
77
+ if ph is not None and tuple(ph.shape) == (vocab_size, n_osc):
78
+ return ph.float(), d.get("mode", "precomputed")
79
+ return None, None