cleanup submission: composed_encoding.py
Browse files- composed_encoding.py +46 -6
composed_encoding.py
CHANGED
|
@@ -37,11 +37,14 @@ AMARK, BMARK, DIVMARK, EQ, ACC, NMARK, REVMARK, NL = "A", "B", "M", "=", "a", "N
|
|
| 37 |
PLSB = "m"
|
| 38 |
|
| 39 |
|
| 40 |
-
def prompt_str(x: int, y: int, p: int, W: int, base: int, subpad: bool = False
|
|
|
|
| 41 |
"""subpad adds p LSB-first to the prompt: the MSB field serves quotient
|
| 42 |
estimation, the LSB field aligns with the LSB-emitted qd*p / remainder
|
| 43 |
chains (per-step diagnostic: subtraction digits need REVERSED access into
|
| 44 |
the MSB-only field — the aligned acc stage learned, the division didn't)."""
|
|
|
|
|
|
|
| 45 |
s = (AMARK + limb_str(x, W, base) + BMARK + limb_str(y, W, base)
|
| 46 |
+ DIVMARK + limb_str(p, W, base, msb_first=True))
|
| 47 |
if subpad:
|
|
@@ -52,7 +55,8 @@ def prompt_str(x: int, y: int, p: int, W: int, base: int, subpad: bool = False)
|
|
| 52 |
def gen_len(W: int, scratch: bool = False, cursor: bool = False,
|
| 53 |
subpad: bool = False, stepidx: bool = False,
|
| 54 |
skiptriv: bool = False, subnum: bool = False,
|
| 55 |
-
bemit: bool = False, srt: bool = False
|
|
|
|
| 56 |
"""Tokens generated after '=': W acc blocks, N restage, quotient, answer.
|
| 57 |
scratch=True: each quotient limb is followed by the running remainder
|
| 58 |
(W limbs, LSB-first) — externalizes the division state, which the model
|
|
@@ -100,6 +104,8 @@ def gen_len(W: int, scratch: bool = False, cursor: bool = False,
|
|
| 100 |
rem errors were 58% unstructured noise, 0.54 even at b=0 -- the
|
| 101 |
install-only borrow supervision never built a circuit; emit the chain
|
| 102 |
(the scratch lesson, applied to the borrow state)."""
|
|
|
|
|
|
|
| 103 |
restage = 1 + (3 if stepidx else 1) * 2 * W
|
| 104 |
pcopy = (1 + W) if skiptriv else 0
|
| 105 |
if srt:
|
|
@@ -144,8 +150,9 @@ def _srt_qd(num: int, p: int, base: int) -> int:
|
|
| 144 |
def build_example(x: int, y: int, p: int, W: int, base: int, scratch: bool = False,
|
| 145 |
cursor: bool = False, subpad: bool = False, stepidx: bool = False,
|
| 146 |
skiptriv: bool = False, subnum: bool = False,
|
| 147 |
-
bemit: bool = False, srt: bool = False
|
| 148 |
-
|
|
|
|
| 149 |
assert not subnum or subpad, "subnum requires subpad"
|
| 150 |
assert not bemit or subnum, "bemit requires subnum"
|
| 151 |
assert not srt or (skiptriv and bemit), "srt requires skiptriv+bemit"
|
|
@@ -178,6 +185,22 @@ def build_example(x: int, y: int, p: int, W: int, base: int, scratch: bool = Fal
|
|
| 178 |
pos += 2 * W
|
| 179 |
assert acc == N
|
| 180 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 181 |
n_msb = to_limbs(N, 2 * W, base, msb_first=True)
|
| 182 |
if stepidx: # restage as (index, limb) pairs
|
| 183 |
parts.append(NMARK + "".join(f"{i:02d}" + limb_char(n_msb[i])
|
|
@@ -212,6 +235,18 @@ def build_example(x: int, y: int, p: int, W: int, base: int, scratch: bool = Fal
|
|
| 212 |
parts.append("".join(limb_char(v) for v in num_c))
|
| 213 |
pos += K
|
| 214 |
qd = _srt_qd(num, p, base)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 215 |
assert abs(num - qd * p) < p, (x, y, p, i, num, qd)
|
| 216 |
ann_g.append((pos, "qhat", qd + base - 1)) # 19-class signed label
|
| 217 |
parts.append(chr(0x90 + base - 1 + qd))
|
|
@@ -331,7 +366,9 @@ def build_example(x: int, y: int, p: int, W: int, base: int, scratch: bool = Fal
|
|
| 331 |
|
| 332 |
|
| 333 |
def var_specs(W: int, base: int, scratch: bool = False, subpad: bool = False,
|
| 334 |
-
srt: bool = False):
|
|
|
|
|
|
|
| 335 |
specs = [("ans", base), ("qhat", 2 * base - 1 if srt else base),
|
| 336 |
("acarry", base)]
|
| 337 |
if subpad: # multiply-carry + subtract-borrow chains
|
|
@@ -345,7 +382,10 @@ def decode_answer(gen_chars: str, W: int, base: int, scratch: bool = False,
|
|
| 345 |
cursor: bool = False, subpad: bool = False,
|
| 346 |
stepidx: bool = False, skiptriv: bool = False,
|
| 347 |
subnum: bool = False, bemit: bool = False,
|
| 348 |
-
srt: bool = False) -> int:
|
|
|
|
|
|
|
|
|
|
| 349 |
# the answer block after the R-mark is W plain limbs in every mode
|
| 350 |
off = gen_len(W, scratch, cursor, subpad, stepidx, skiptriv, subnum, bemit,
|
| 351 |
srt) - W
|
|
|
|
| 37 |
PLSB = "m"
|
| 38 |
|
| 39 |
|
| 40 |
+
def prompt_str(x: int, y: int, p: int, W: int, base: int, subpad: bool = False,
|
| 41 |
+
mulonly: bool = False) -> str:
|
| 42 |
"""subpad adds p LSB-first to the prompt: the MSB field serves quotient
|
| 43 |
estimation, the LSB field aligns with the LSB-emitted qd*p / remainder
|
| 44 |
chains (per-step diagnostic: subtraction digits need REVERSED access into
|
| 45 |
the MSB-only field — the aligned acc stage learned, the division didn't)."""
|
| 46 |
+
if mulonly: # tier 0: pure multiplication
|
| 47 |
+
return AMARK + limb_str(x, W, base) + BMARK + limb_str(y, W, base) + EQ
|
| 48 |
s = (AMARK + limb_str(x, W, base) + BMARK + limb_str(y, W, base)
|
| 49 |
+ DIVMARK + limb_str(p, W, base, msb_first=True))
|
| 50 |
if subpad:
|
|
|
|
| 55 |
def gen_len(W: int, scratch: bool = False, cursor: bool = False,
|
| 56 |
subpad: bool = False, stepidx: bool = False,
|
| 57 |
skiptriv: bool = False, subnum: bool = False,
|
| 58 |
+
bemit: bool = False, srt: bool = False,
|
| 59 |
+
mulonly: bool = False) -> int:
|
| 60 |
"""Tokens generated after '=': W acc blocks, N restage, quotient, answer.
|
| 61 |
scratch=True: each quotient limb is followed by the running remainder
|
| 62 |
(W limbs, LSB-first) — externalizes the division state, which the model
|
|
|
|
| 104 |
rem errors were 58% unstructured noise, 0.54 even at b=0 -- the
|
| 105 |
install-only borrow supervision never built a circuit; emit the chain
|
| 106 |
(the scratch lesson, applied to the borrow state)."""
|
| 107 |
+
if mulonly: # acc rows + answer copy
|
| 108 |
+
return W * (1 + 2 * W) + 1 + 2 * W
|
| 109 |
restage = 1 + (3 if stepidx else 1) * 2 * W
|
| 110 |
pcopy = (1 + W) if skiptriv else 0
|
| 111 |
if srt:
|
|
|
|
| 150 |
def build_example(x: int, y: int, p: int, W: int, base: int, scratch: bool = False,
|
| 151 |
cursor: bool = False, subpad: bool = False, stepidx: bool = False,
|
| 152 |
skiptriv: bool = False, subnum: bool = False,
|
| 153 |
+
bemit: bool = False, srt: bool = False, mulonly: bool = False,
|
| 154 |
+
srt_dither: float = 0.0):
|
| 155 |
+
"""Return (text, ann). x,y < p < base**W (mulonly: x,y < base**W)."""
|
| 156 |
assert not subnum or subpad, "subnum requires subpad"
|
| 157 |
assert not bemit or subnum, "bemit requires subnum"
|
| 158 |
assert not srt or (skiptriv and bemit), "srt requires skiptriv+bemit"
|
|
|
|
| 185 |
pos += 2 * W
|
| 186 |
assert acc == N
|
| 187 |
|
| 188 |
+
if mulonly: # tier 0: answer = N itself
|
| 189 |
+
parts.append(NMARK)
|
| 190 |
+
pos += 1
|
| 191 |
+
n_l = to_limbs(N, 2 * W, base)
|
| 192 |
+
for k in range(2 * W):
|
| 193 |
+
ann_g.append((pos + k, "ans", n_l[k]))
|
| 194 |
+
parts.append(limb_str(N, 2 * W, base) + NL)
|
| 195 |
+
pos += 2 * W + 1
|
| 196 |
+
prompt = prompt_str(x, y, p, W, base, mulonly=True)
|
| 197 |
+
text = prompt + "".join(parts)
|
| 198 |
+
assert len(text) == len(prompt) + gen_len(W, mulonly=True) + 1
|
| 199 |
+
ann = [dict() for _ in range(len(text))]
|
| 200 |
+
for gi, var, val in ann_g:
|
| 201 |
+
ann[len(prompt) + gi - 1][var] = int(val)
|
| 202 |
+
return text, ann
|
| 203 |
+
|
| 204 |
n_msb = to_limbs(N, 2 * W, base, msb_first=True)
|
| 205 |
if stepidx: # restage as (index, limb) pairs
|
| 206 |
parts.append(NMARK + "".join(f"{i:02d}" + limb_char(n_msb[i])
|
|
|
|
| 235 |
parts.append("".join(limb_char(v) for v in num_c))
|
| 236 |
pos += K
|
| 237 |
qd = _srt_qd(num, p, base)
|
| 238 |
+
if srt_dither:
|
| 239 |
+
# Deterministic pseudo-random alternate-digit training: SRT's
|
| 240 |
+
# redundancy makes qd+-1 often equally valid, but the model
|
| 241 |
+
# only ever saw label-digit continuations -- free-running it
|
| 242 |
+
# sometimes picks the OTHER valid digit and must continue
|
| 243 |
+
# consistently from its own choice. Dithered traces teach
|
| 244 |
+
# exactly those continuations. (hash-derived: reproducible)
|
| 245 |
+
h = hash((x, y, p, i)) & 0xFFFF
|
| 246 |
+
if h < int(srt_dither * 0x10000):
|
| 247 |
+
alt = qd + (1 if h & 1 else -1)
|
| 248 |
+
if abs(alt) <= base - 1 and abs(num - alt * p) < p:
|
| 249 |
+
qd = alt
|
| 250 |
assert abs(num - qd * p) < p, (x, y, p, i, num, qd)
|
| 251 |
ann_g.append((pos, "qhat", qd + base - 1)) # 19-class signed label
|
| 252 |
parts.append(chr(0x90 + base - 1 + qd))
|
|
|
|
| 366 |
|
| 367 |
|
| 368 |
def var_specs(W: int, base: int, scratch: bool = False, subpad: bool = False,
|
| 369 |
+
srt: bool = False, mulonly: bool = False):
|
| 370 |
+
if mulonly: # tier 0: multiply only
|
| 371 |
+
return [("ans", base), ("acarry", base)]
|
| 372 |
specs = [("ans", base), ("qhat", 2 * base - 1 if srt else base),
|
| 373 |
("acarry", base)]
|
| 374 |
if subpad: # multiply-carry + subtract-borrow chains
|
|
|
|
| 382 |
cursor: bool = False, subpad: bool = False,
|
| 383 |
stepidx: bool = False, skiptriv: bool = False,
|
| 384 |
subnum: bool = False, bemit: bool = False,
|
| 385 |
+
srt: bool = False, mulonly: bool = False) -> int:
|
| 386 |
+
if mulonly: # answer = 2W limbs after 'N'
|
| 387 |
+
off = gen_len(W, mulonly=True) - 2 * W
|
| 388 |
+
return parse_limbs(gen_chars[off:off + 2 * W], base)
|
| 389 |
# the answer block after the R-mark is W plain limbs in every mode
|
| 390 |
off = gen_len(W, scratch, cursor, subpad, stepidx, skiptriv, subnum, bemit,
|
| 391 |
srt) - W
|